用回调返回结果
我想查询一个数据库,然后从结果中创建一个对象数组,将它们变成一个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
没有运气。
有人可以解释我怎么可以得到这段代码与回调工作?
回调函数是一个作为参数传递给另一个函数的函数,然后在外函数内调用该函数来完成某种例程或动作。
回调是讲述一个功能下一步做什么,如“大功告成后,运行该功能”的一种方式。
例如:
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
,那么无论你想与调用的结果,这样做需要在回调中完成。
请记住,异步函数不会返回您通常想要的最终值(通常它们会返回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
适适用范围访问的变量,如resultsArray
和callback
。
希望有所帮助。
也许你想检查* ES7的异步功能(异步/等待)*。例如。这[介绍](http://rossboucher.com/await/) – oneturkmen
learnyounode是一个很好的教程,如果你还没有尝试过https://github.com/workshopper/learnyounode –