2017-08-25 152 views
0

我想查询一个数据库,然后从结果中创建一个对象数组,将它们变成一个JSON对象。用回调返回结果

我不习惯Javascript的异步性,我真的很困惑如何实现需要同步工作的东西。我知道我可能需要使用回调,但在看了很多教程后,我只剩下更多的困惑。

这是不进行回调的代码:

var foreignTable = (tablename,idArr)=>{ 
 
\t var dataArray = []; 
 
\t //call a query for each of the ids 
 
\t var objectToAdd; 
 
\t for(var id of idArr){ 
 
\t \t objectToAdd = queryForeignTable(tablename,id); 
 
\t \t dataArray.push(objectToAdd); 
 
\t } 
 
\t return dataArray; 
 
\t 
 
connection.end(); 
 
}; 
 

 
var queryForeignTable = (tablename,id)=>{ 
 
\t connection.query("SELECT * FROM "+tablename+" WHERE id="+id, function (error, results, fields) { 
 
\t if(error)throw error; 
 
\t var objectToAddToArray={}; 
 
\t //Go through each field in a result and make the object 
 
\t for(packet of fields){ 
 
\t \t var label = packet.name; 
 
\t \t objectToAddToArray[label] = results[0][label]; 
 
\t } 
 
\t 
 
\t return objectToAddToArray; 
 

 
}); 
 
}; 
 

 
var arrayOfDrivers = foreignTable("driver",[1,2]); 
 
    
 
outputJson["drive"]=arrayOfDrivers; 
 

 
console.log(outputJson); // { drive: [ undefined, undefined ] }

我试图foreignTable(tablename, idArr, callback)有回调调用queryForeignTable没有运气。

有人可以解释我怎么可以得到这段代码与回调工作?

+1

也许你想检查* ES7的异步功能(异步/等待)*。例如。这[介绍](http://rossboucher.com/await/) – oneturkmen

+0

learnyounode是一个很好的教程,如果你还没有尝试过https://github.com/workshopper/learnyounode –

回答

0

回调函数是一个作为参数传递给另一个函数的函数,然后在外函数内调用该函数来完成某种例程或动作。

MDN: Callback function

回调是讲述一个功能下一步做什么,如“大功告成后,运行该功能”的一种方式。

例如:

first = function (callback) { 
    console.log("First!"); 
    callback(); 
} 

second = function() { 
    console.log("Second!"); 
} 

first(second); 

会产生:

First! 
Second! 

您也可以使用匿名函数产品相同的结果:

first(function() { 
    console.log("Second!") 
}); 

关于从你的问题的具体例子,你是正确的,你需要使用回调有点不同。您不需要在两个函数中使用return语句,而需要使用回调函数。 connection.query与您的结果异步返回为results,但您不能将return转换为您的queryForeignTable函数。而是给queryForeignTable一个回调函数来运行。您的foreignTable函数也有同样的想法。

我没有连接到数据库,很明显,所以我掐灭一个数据库连接和简化你想要做什么,但它应该是这个样子:

// Stubbed DB connection 
var connection = {}; 
connection.query = (id, cb) => { 
    var results = [ 
    { 
     id: id, 
     name: 'Name of ' + id, 
    }, 
    ]; 
    cb(null, results); 
}; 

var foreignTable = (ids, cb) => { 
    var data = []; 
    for (var i = 0; i < ids.length; i++) { 
    queryForeignTable(ids[i], (error, obj) => { 
     data.push(obj); 
     if (i == ids.length - 1) { 
     cb(null, data); 
     } 
    }); 
    } 
}; 

var queryForeignTable = (id, cb) => { 
    connection.query(id, (error, results) => { 
    if (error) { 
     cb(error, null); 
    } 
    cb(null, results[0]); 
    }); 
}; 

foreignTable([1, 2], (error, data) => { 
    if (error) { 
    console.error(error); 
    } 
    console.log(data); 
}); 

产生:

[ { id: 1, name: 'Name of 1' }, { id: 2, name: 'Name of 2' } ] 

从本质上说,当你有一种冲动,return在异步方式的函数一些值(S),给函数的回调参数,然后调用你的返回值该回调。

您可以运行此代码:当你有一个异步调用,就像connection.query(statement, callback)https://repl.it/K0YI/3

0

,那么无论你想与调用的结果,这样做需要在回调中完成。

请记住,异步函数不会返回您通常想要的最终值(通常它们会返回undefined)。而不是使用返回值,而是通过回调来表达,“当你完成时,继续并结果做这件事”,又如。延续传球风格。

您代码中的一个挑战是您要为每个ID分别发出查询,然后将结果汇总到一个响应数组中。这意味着您需要检查所有查询何时完成,然后才能显示最终结果。

下面是您的示例,重新编写,评论和简化。希望这有助于解释控制流程如何工作。

// Read row IDs 1 and 2 from the "driver" table. 
readTable("driver", [1, 2], displayData); 

// Print the results. 
function displayData (arrayOfDrivers) { 
    console.log(arrayOfDrivers); 
} 

// Read all rows matching IDs in `idArray` from `tableName`, 
// put results into an array, and finally invoke `callback`. 
function readTable (tablename, idArray, callback) { 
    var resultsArray = []; 

    // Queue up all the async queries. 
    for (var id of idArray){ 
     queryTable(table, id, handleResponse); 
    } 

    // A query finished, so handle the result. 
    function handleResponse (error, results, fields) { 
     if (error) { 
      throw error; 
     } 

     // Add the query result to array of results. 
     resultsArray.push(results[0]); 

     // Check if all queries are done. 
     if (resultsArray.length === idArray.length) { 
      // Invoke the callback with the resultsArray. 
      // The callback is in fact the `displayData` function. 
      callback(resultsArray); 
     } 
    } 
} 

// Execute a query, using the `cb` callback to handle the response. 
function queryForeignTable (tablename, id, cb) { 
    var query = "SELECT * FROM " + tablename + " WHERE id=" + id; 
    connection.query(query, cb); 
} 

注意,handleResponse函数在readTable功能的范围内定义的,所以它可以在readTable适适用范围访问的变量,如resultsArraycallback

希望有所帮助。