function inboxUsers(){
for (var i=0; i<uniqueArray.length; i++){
var getUsername = 'SELECT userName FROM users WHERE userId = ' + uniqueArray[i];
db.query(getUsername, function(err, results) {
if (err) {
console.log('Error in database');
throw err;
}
for(var i in results){
console.log('single',results[i].userName);
inboxUserList.push(results[i].userName);
}
});
}
sample();
}
function sample(){
console.log('same function');
}
这是我的控制台输出。
same function
single user1
single user2
single user3
在这段代码中,我在for循环之后调用了函数 sample(),但是在循环结束之前它调用了 sample()函数。
我想在for循环结束时调用sample()函数。我是stackoverflow的初学者,如果我有错误请向我道歉。谢谢
答案 0 :(得分:5)
您对db.query
的呼叫是异步的。这意味着什么:
对db.query(...)
的调用会立即返回,不会返回任何内容。
不是将返回值赋给变量(var results = db.query(...)
),而是传递callback function作为参数,以便db模块可以在完成提取时调用结果。它将挂起到回调函数,直到数据库有结果,然后它会在函数准备就绪时调用它。
因为对db.query(...)
的调用立即返回,所以for循环将完成,并且在您提供给查询的回调函数被db模块调用之前将调用sample()
要确保在完成所有通话后sample
运行,您需要跟踪每个查询的完成情况,然后在所有查询都返回后触发sample
函数。在我看来,最简单的方法是在不向您介绍复杂主题的情况下执行此操作,例如&#34; promises&#34;,使用名为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');
}
这里又是一次,但采用了更少的快捷方式和详细的评论。
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
lib知道你向数组提供了多少函数,因此它知道在调用最终函数之前它应该等待多少次done
。
答案 1 :(得分:1)
您很可能遇到此问题,因为您的db.query()
功能不同步。它需要一个可以在完成后调用的回调函数。
在数据库库查询数据库并获得结果之前,不会调用代码inboxUserList.push(...)
。同时,你的for循环将继续运行,准备好所有查询并在完成之前继续。然后调用sample()
,因为for循环已完成,即使您传入的回调尚未被调用。
有许多解决方案,但最简单的当前代码可能是这样的:
function inboxUsers(){
var completed = 0;
for (var i=0; i<uniqueArray.length; i++){
var getUsername = 'SELECT userName FROM users WHERE userId = ' + uniqueArray[i];
db.query(getUsername, function(err, results) {
if (err) {
console.log('Error in database');
throw err;
}
for(var i in results){
console.log('single',results[i].userName);
inboxUserList.push(results[i].userName);
}
completed++;
if (completed == uniqueArray.length) {
sample();
}
});
}
}
function sample(){
console.log('same function');
}