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

yat*_*van 1 javascript for-loop function node.js

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');
}
Run Code Online (Sandbox Code Playgroud)

这是我的控制台输出.

same function
single user1
single user2
single user3
Run Code Online (Sandbox Code Playgroud)

在这段代码中,我在for循环之后调用了函数sample(),但是在循环结束之前调用了sample()函数.

我想在for循环结束时调用sample()函数.我是stackoverflow的初学者,如果我有错误请向我道歉.谢谢

Che*_*hev 5

你的电话db.query是异步的.这意味着什么:

  1. 呼叫db.query(...)立即返回,什么都不返回.

  2. 您不是将返回值赋给变量(var results = db.query(...)),而是将回调函数作为参数传递,以便db模块在完成获取结果时可以调用.它将挂起到回调函数,直到数据库有你的结果,然后它会在它准备好时调用它.

  3. 因为调用db.query(...)立即返回,所以for循环将完成,并且在sample()您提供给查询的回调函数之前将调用将在db模块调用之前调用.


要确保sample在完成所有调用后运行,您需要跟踪每个查询的完成情况,然后在sample返回所有查询时触发该函数.在我看来,最简单的方法是在不向您介绍像"promises"这样的复杂主题的情况下,使用名为async的模块及其并行方法.

$ 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');
}
Run Code Online (Sandbox Code Playgroud)

这里又是一次,但采用的捷径更少,详细的评论.

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');
}
Run Code Online (Sandbox Code Playgroud)

asyncLIB知道你提供给阵列多少功能,所以它知道很多电话怎么done也应该调用最终功能之前等待.