当循环在Node js中完成时调用函数 [英] Call function when for loop finished in Node js

查看:168
本文介绍了当循环在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;
$ b console.log('single',results [i] .userName);
inboxUserList.push(results [i] .userName)
$ ;
}
});
}
sample();


函数sample(){
console.log('same function');

$ / code>

这是我的控制台输出。

 相同的功能
单用户1
单用户2
单用户3

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

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

解决方案

您对 db.query 的调用是异步的。这意味着什么:


  1. 调用 db.query(...)立即返回,不返回任何结果。

  2. 不是将返回值赋给变量( var results = db。查询(...)),你传入一个回调函数作为参数,以便db模块在完成获取其结果时可以调用它。它将挂起回调函数,直到数据库有结果,然后它会在准备就绪时调用函数。

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

  4. 为确保在所有调用完成后运行 sample ,您需要跟踪每个查询的完成情况,然后触发示例函数在所有查询都返回时执行。在我看来,最简单的方法是在不向你介绍像promises这样复杂的主题的情况下完成这个任务,这个模块叫做异步和它的并行方法。


    $ npm install async --save




      var async = require('async'); 
    var queries = [];

    函数inboxUsers(){
    uniqueArray.forEach(function(userId){
    var getUsername ='SELECT userName FROM users WHERE userId ='+ userId;
    queries .push(function(done){
    db.query(getUsername,done);
    });
    });
    async.parallel(query,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();
    });


    函数sample(){
    console.log('same function');
    }






    使用更少的捷径和详细的评论。

      var async = require('async'); 

    //创建一个数组来存储一堆函数,即异步库
    //应该启动并等待完成。
    var queries = [];

    函数inboxUsers(){
    uniqueArray.forEach(function(userId){
    var getUsername ='SELECT userName FROM users WHERE userId ='+ userId;
    var queryFunc = function(done){
    db.query(getUsername,function(err,results){
    //让异步库知道这个查询已经完成
    //第一个参数是希望是一个错误
    //如果err为null或未定义,那么异步lib
    //将忽略它,第二个参数应该是我们的结果
    done(err,results );
    });

    //通过传递
    // done函数作为db.query的回调函数,可以使上面的代码变得更简单。 $ b //不希望这样做让你感到困惑。
    // db.query(getUsername,done);
    };
    queries.push(queryFunc);
    });
    //通过传入我们的查询数组来激发所有的异步函数。
    //异步库将在它调用以下最终函数之前等待它们全部调用done()
    // //。
    async.parallel(查询,函数(err,allQueryResults){
    //如果我们的任何查询传递一个错误到完成,那么异步
    // lib将暂停其余的查询并立即调用
    //此函数传递错误
    if(err){return console.error(err);}

    // queryResults是一个包含每个查询结果的数组
    allQueryResults.forEach(function(queryResults){
    queryResults.forEach(function(result){
    console.log('single',result。 userName);
    inboxUserList.push(result.userName);
    });
    });

    //所有的查询都完成了,你的inboxUserList数组$现在我们可以调用
    //sample。
    sample();
    });
    //被填充了您之后的数据。
    }

    函数sample(){
    console.log('same function');

    async lib知道你提供给该数组的多少函数,以便知道在调用最终函数之前应该等待多少次调用 done


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

    This is my console output.

    same function
    single user1
    single user2
    single user3
    

    In this code I called the function sample() after for loop, but it called the sample() function before for loop ends.

    I want to call the sample() function when for loop ends. I am a beginner for stackoverflow, if i have error please apologize me. Thank you

    解决方案

    Your call to db.query is asynchronous. What that means is this:

    1. The call to db.query(...) returns immediately, returning nothing.

    2. Instead of assigning a return value to a variable (var results = db.query(...)), you pass in a callback function as an argument so that the db module can call when it's done fetching its results. It will hang onto the callback function until the database has your results, then it will call the function when it's ready.

    3. Because the call to db.query(...) returns immediately, your for loop will complete and the call to sample() will fire before the callback functions you supplied to your queries are ever called by the db module.


    To ensure that sample runs when all of your calls are done, you'll need to track the completion of each query and then fire the sample function when all of the queries have returned. In my opinion, the easiest way to do this without introducing you to complex topics like "promises", is with a module called async and its parallel method.

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


    Here it is again but with fewer shortcuts taken and detailed comments.

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

    The async lib knows how many functions you supplied to the array so it knows how many calls to done it should wait for before invoking the final function.

    这篇关于当循环在Node js中完成时调用函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆