在Node js中完成for循环时调用函数

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,如果我有错误,请道歉。 谢谢

你对db.query调用是asynchronous的。 这意味着什么:

  1. db.query(...)的调用立即返回,不返回任何内容。

  2. 而不是分配一个返回值给一个variables( var results = db.query(...) ),你传入一个callback函数作为参数,以便db模块可以在获取结果时调用。 它将挂起callback函数,直到数据库有结果,然后在准备就绪时调用函数。

  3. 由于调用db.query(...)立即返回,您的for循环将会完成,调用sample()将在您提供给查询的callback函数被db模块调用之前触发。


为确保在所有调用完成后运行sample ,您需要跟踪每个查询的完成情况,并在所有查询都返回时触发sample函数。 在我看来,最简单的方法是在没有向你介绍像“promise”这样复杂的主题的情况下做到这一点,就是使用称为async的模块和它的并行方法。

$ npm安装asynchronous – 保存

 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'); } 

这里又是一个捷径,只有更less的捷径和详细的评论。

 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库知道你提供给数组的多less个函数,以便知道在调用最终函数之前应该等待多less次调用。

你很可能遇到这个问题,因为你的db.query()函数是不同步的。 它期望一个callback函数,它可以在完成时调用。

你的代码inboxUserList.push(...)将不会被调用,直到你的数据库库查询数据库并得到结果。 同时,您的for循环将继续运行,准备好所有查询,并在所有查询完成之前继续运行。 然后调用sample() ,因为for循环已经完成,即使你传入的callback函数尚未被调用。

有很多解决scheme,但是最简单的代码可能是这样的:

 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'); }