Node.js:forEach在async.series中

时间:2013-10-20 08:18:25

标签: javascript json node.js asynchronous foreach

我开始开发我的node.js应用程序,但我不能“认为异步”。 在我的函数中,我必须进行查询,并且对于每一行,我必须执行另一个查询来计算最终结果并创建我的json。 我试着这样做:

async.series([
    function(callback) {
            db.myCannedResponseList(req.params.websiteid, function(err,questions) {
                if (err) return callback(err);
                ...
                callback();
            });
        },
    function(callback) {
            async.forEachSeries(temp,function(quest,callback) {
                    db.getCannedAnswer(quest.id, function(err,answers) {
                         console.log(answers);
                    });
            }, function(err) {
                if (err) return next(err);
            });
            callback();
        }
    ],
        function(err) { 
            if (err) return next(err);
            res.json(output);
    });

但是有一个问题: resCannedAnswer 的结果显示在 res.json(输出)之后。 我该如何解决?

2 个答案:

答案 0 :(得分:5)

您需要在forEachSeries完成后调用回调。您还需要调用传递给forEachSeries处理函数的回调函数:

async.forEachSeries(temp, function(quest, callback2) {
  db.getCannedAnswer(quest.id, function(err, answers) {
    console.log(answers);
    // call the callback for forEachSeries so it can proceed:
    callback2(); 
  });
}, callback); // forEachSeries is done here, call the callback for async.series

答案 1 :(得分:0)

您的异步函数是嵌套的,因此需要成为您的回调函数。

这是一种方法:

    async.series([
        //async.apply(db.myCannedResponseList,req.params.websiteid), // This is equivalent to the first function below
        //db.myCannedResponseList(req.params.websiteid,callback), // This is equivalent too
        function(callback) {
            db.myCannedResponseList(req.params.websiteid, callback);
        },    
        function(callback) {
            // I'm not sure forEach is the best choice here
            // since it's callback isn't called with all the results so it won't be able to be forwarded...
            // Personally, I use async.times for something like this.
            async.times(temp.length,function(i,next) {
                db.getCannedAnswer(temp[i].id,next);
            },callback)
        }
     ],function(err) { 
          if (err) return next(err);
          res.json(output);
    });

我不确定此功能应该做什么,但如果您在async.series中遇到错误,则应成功拨打res.json(500,error)或不致电res

一个好的方法是完全分离这个函数,并在完成后调用另一个回调函数。然后,您可以在那里拨打res

此外,不是将数组传递给async.series,而是可以传递一个对象,因此结果将被命名空间。

完整示例:

    function getCannedStuff(data,callback){
        async.series({
            list : async.apply(db.myCannedResponseList,data.websiteid),
            answer : function(cb) {
                async.times(data.temp.length,function(i,next) {
                db.getCannedAnswer(data.temp[i].id,next);
                },cb)
            }
        },callback);  
    }

然后从另一个模块调用该函数:

    getCannedStuff({
        websiteid: req.params.websiteid,
        temp:temp
    },function(error,results) {
        console.log(results.list);
        console.log(results.answer);
        if(err) return res.json(500,{error : error});
        res.json(results)
    });

您应该决定是否要控制getCannedStuff内部或外部的错误,但这是传递它们的好方法,而不是一直if(err)查看它们是否发生。