您对db.query 的调用是异步的。这是什么意思:
对db.query(...) 的调用立即返回,什么也不返回。
您无需将返回值分配给变量 (var results = db.query(...)),而是将 callback function 作为参数传递,以便 db 模块在完成获取结果时可以调用。它会挂在回调函数上,直到数据库有你的结果,然后它会在它准备好时调用该函数。
因为对 db.query(...) 的调用会立即返回,所以您的 for 循环将完成,并且对 sample() 的调用将在您提供给查询的回调函数被 db 模块调用之前触发。
为确保在所有调用完成后sample 运行,您需要跟踪每个查询的完成情况,然后在所有查询返回时触发sample 函数。在我看来,不向您介绍“承诺”等复杂主题的最简单方法是使用名为 async 的模块及其 parallel 方法。
$ npm install async --save
var async = require('async');
var queries = [];
function inboxUsers(){
uniqueArray.forEach(function (userId) {
var getUsername = 'SELECT userName FROM users WHERE userId = ' + userId;
queries.push(function (done) {
db.query(getUsername, done);
});
});
async.parallel(queries, function (err, allQueryResults) {
if (err) { return console.error(err); }
allQueryResults.forEach(function (queryResults) {
queryResults.forEach(function (result) {
console.log('single', result.userName);
inboxUserList.push(result.userName);
});
});
sample();
});
}
function sample(){
console.log('same function');
}
又来了,但使用的快捷方式更少,cmets 更详细。
var async = require('async');
// create an array to store a bunch of functions that the async library
// should fire and wait to finish.
var queries = [];
function inboxUsers(){
uniqueArray.forEach(function (userId) {
var getUsername = 'SELECT userName FROM users WHERE userId = ' + userId;
var queryFunc = function (done) {
db.query(getUsername, function(err, results) {
// let the async lib know this query has finished.
// the first argument is expected to be an error.
// If the err is null or undefined then the async lib
// will ignore it. The second argument should be our results.
done(err, results);
});
// You could make the above even simpler by just passing
// the done function as the callback to db.query. I just
// didn't want to confuse you by doing that.
// db.query(getUsername, done);
};
queries.push(queryFunc);
});
// Fire all async functions by passing in our queries array.
// The async library will wait for them all to call "done()"
// before it invokes this final function below.
async.parallel(queries, function (err, allQueryResults) {
// If any of our queries pass an error to "done" then the async
// lib will halt the rest of the queries and immediately invoke
// this function, passing in the error.
if (err) { return console.error(err); }
// queryResults is an array containing the results of each query we made.
allQueryResults.forEach(function (queryResults) {
queryResults.forEach(function (result) {
console.log('single', result.userName);
inboxUserList.push(result.userName);
});
});
// All your queries are complete and your inboxUserList array
// is populated with the data you were after. Now we can call
// "sample".
sample();
});
}
function sample(){
console.log('same function');
}
async 库知道您向数组提供了多少函数,因此它知道在调用最终函数之前应该等待多少次对 done 的调用。