【问题标题】:nodejs send variable to asynchronous function and determine end of tasksnodejs将变量发送到异步函数并确定任务结束
【发布时间】:2015-05-28 07:44:33
【问题描述】:

我正在进行多个异步数据库查询,并尝试将所有这些数据存储在一个大列表中,当所有查询完成后,我想将此数据作为响应发送。

我面临两个问题,

  1. 如何判断异步调用结束

  2. 如何将变量传递给异步函数,以便将其结果存储在此变量中,以便我以后使用

功能说明

我有一个应用程序,它在后台每 k 分钟执行一次,并且在每次执行时,任务信息都保存在 mongodb 数据库中。我在完成时遇到问题的函数称为 fetchHistoryStatistics。该函数应该获取每天执行的执行次数。

算法:

  1. 获取所有不同的执行日期(年-月-日)
  2. 获取所有正在执行的不同帐户
  3. 为每个用户获取每天的执行次数

代码:

function fetchHistoryStatistics(response){
    var dates = [], timeline = {}, query;
    //Distinct Dates
    db.collection('master')
        .distinct("date", function(err, ds){

            for(var i in ds){
                var d = ds[i].getFullYear() + " " + (ds[i].getMonth()+1) + " " + ds[i].getDate();
                if (dates.indexOf(d)==-1){
                    dates.push(d);
                }
            }

            //Distinct Users
            db.collection('master')
                .distinct("screen_id", function(err, users){
                    //Fetching History Data
                    for(var i in users){
                        timeline[users[i]]={};
                        for (var j in dates){
                            timeline[users[i]][dates[j]] = {};
                            if(dates[parseInt(j)+1] != undefined){
                                query = {"screen_id": {"$eq": users[i]}
                                    , "date": {"$gte": new Date(dates[j]), "$lt": new Date(dates[parseInt(j)+1])
                                    }};
                                db.collection('master')
                                    .find(query)
                                    .toArray(function(err, results){
                                       // **!! TODO !!** 
                                       // The problem is occuring here, when i try to store the data in the variable timeline
                                        timeline[users[i]][dates[j]] = results.length;
                                        console.log("-----------------", users[i], dates[j]);
                                        //console.log(query);
                                        //console.log(results);

                                        console.log("timeline :", timeline);
                                    })
                                ;
                            }else{
                                query = {"screen_id": {"$eq": users[i]}
                                    , "date": {"$gte": new Date(dates[j])
                                    }};

                                db.collection('master')
                                    .find(query)
                                    .toArray(function(err, results){
                                        timeline[users[i]][dates[j]] = results.length;
                                        console.log("-----------------", users[i], dates[j]);
                                        //console.log(query);
                                        //console.log(results);

                                        console.log("timeline :", timeline);
                                    })
                                ;
                            }
                        }
                    }
                    console.log("timeline :", timeline);
                })
            ;

        })
    ;


    // !! TODO !!
    // And another problem here
    // Because the functions are Asynchronous i need to be able to wait for all the executions to have terminated,
    // such that i can send all the collected data back in the response
    response.send({});

}

【问题讨论】:

  • 查看这个答案,我认为 Promise 会让这更容易使用:stackoverflow.com/a/23771854/693275
  • 当您运行 FOR 循环时,您会失去异步性 ,因为它们都无需等待即可执行。您是否尝试过使用 Caolan 的 asyn 库来迭代这些数组?类似 async.eachSeries(dates, function(d, callback) { // 处理 d,然后回调执行下一个数组项 }));

标签: javascript node.js mongodb asynchronous


【解决方案1】:

正如我的评论所说,我认为使用 bluebird 来承诺图书馆将使这更容易使用和推理。如果您没有使用 Promise(它允许您同步处理异步代码),那么通常处理这种情况的方式是通过您的函数的回调参数。

function fetchHistoryStatistics(response, callback){ ...

然后,一旦您完成了数据操作,您就可以使用最终数据调用提供的回调:

//Fetching History Data
for(var i in users){
  ...
}
console.log("timeline :", timeline);
// fire callback function with timeline as argument
callback(timeline);

您的调用代码将采用以下形式:

fetchHistoryStatistics(response, function(timeline) { ... });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-04
    • 1970-01-01
    • 1970-01-01
    • 2020-10-05
    • 1970-01-01
    相关资源
    最近更新 更多