我尝试查询数据库,然后从结果中创建一个对象数组,将它们转换为JSON对象。
我不熟悉Javascript的异步性质,我真的很困惑如何实现需要同步工作的东西。我知道我可能需要使用回调,但在看了很多教程之后我才会感到困惑。
这是没有回调的代码:
var foreignTable = (tablename,idArr)=>{
var dataArray = [];
//call a query for each of the ids
var objectToAdd;
for(var id of idArr){
objectToAdd = queryForeignTable(tablename,id);
dataArray.push(objectToAdd);
}
return dataArray;
connection.end();
};
var queryForeignTable = (tablename,id)=>{
connection.query("SELECT * FROM "+tablename+" WHERE id="+id, function (error, results, fields) {
if(error)throw error;
var objectToAddToArray={};
//Go through each field in a result and make the object
for(packet of fields){
var label = packet.name;
objectToAddToArray[label] = results[0][label];
}
return objectToAddToArray;
});
};
var arrayOfDrivers = foreignTable("driver",[1,2]);
outputJson["drive"]=arrayOfDrivers;
console.log(outputJson); // { drive: [ undefined, undefined ] }

我尝试foreignTable(tablename, idArr, callback)
使用回调调用queryForeignTable
而没有运气。
有人可以解释一下如何让这段代码与回调一起使用吗?
答案 0 :(得分:0)
回调函数是作为参数传递给另一个函数的函数,然后在外部函数内调用该函数以完成某种例程或操作。
回调是告诉函数下一步操作的一种方式,如“完成后,运行此函数”。
例如:
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
函数中的某些值时,给函数一个回调参数,然后用你的返回值调用该回调。
您可以在此处运行代码:https://repl.it/K0YI/3
答案 1 :(得分:0)
当您进行异步调用时,如connection.query(statement, callback)
,那么无论您想对该调用的结果做什么,都需要在回调中完成。
请记住,异步函数不会返回您通常想要的最终值(通常它们会返回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
和{ {1}}。
希望有所帮助。