NodeJS:在for循环中调用回调函数

时间:2013-11-21 09:00:58

标签: javascript node.js callback

基本上,我试图调用一个函数,其中一个循环正在运行,其中存在许多回调函数(回调地狱)..如下所示:

for(var i=0;i<data.id.length;i++)
{
    DAO.getUserById(data.id[i],function(err,resp1)
    {
       /* some other work based on resp1 */
       DAO.getOtherData(resp1.username,resp1.userId,function(err,resp2)
       {
           /* similary some other work*/
       });
    });
}  

我在我的应用程序中的多个位置都有相同的模式,有时我遇到回调问题,for循环结束,但回调没有给出响应,看起来DAO方法已被调用但仍在等待响应。 有没有优化的方法来克服这个问题?

很高兴知道是否有一些javascript编码模式可以解决这个问题。(除了任何第三方库)谢谢

3 个答案:

答案 0 :(得分:3)

你听说过延期或承诺吗?我认为这就是你要找的东西。在它的基本形式中,它基本上是一个有两个处理程序的对象。一个是失败,一个是成功。

但还有其他辅助函数,如然后 ,它允许您以更易读的方式链接函数。看看q或jQuery实现。有关非常好的介绍,请阅读“异步JavaScript”一书。

编辑:/

我为你做了js fiddle一个小工作示例。

    var data = { id : [] };

    for(var i = 0; i < 10; i++) {
        data.id.push(i);
    }

    // DAO definition
    var DAO = {
        getUserById : function(id) {
            var deferred = $.Deferred();

            setTimeout(function() { 
                var isError = Math.floor(Math.random()*11) > 5;

                if(isError) {
                    deferred.reject("WOW - Much Handler - So error");
                } else {
                    deferred.resolve({
                        username :  'Max',
                        userId : id
                    }); 
                }
            }, 50);

            return deferred.promise();
        },

        getOtherData : function(username, userId) {
            var deferred = $.Deferred();

            setTimeout(function() {
                deferred.resolve((username + ' id: ' + userId));
            }, 20);

            return deferred.promise();
        }
    };



    function printResult(res) {
        $('#result').html($('#result').html() + '<br />' + res);
    };

    // DAO usage

    for(var i=0;i<data.id.length;i++)
    {
        DAO.getUserById(data.id[i])
        .done(function(res) {
            DAO.getOtherData(res.username, res.userId).done(function(result) {
                printResult(result);
            });
        })
        .fail(function(res) {
            printResult(res);
        });
    }

这样做的巨大优势是双重的:

  1. 您可以免费分离错误处理程序代码和结果处理程序代码
  2. 它可以防止你嵌套地狱。 (回调,回调,回调......)由于延迟,你可以将实际逻辑输出。
  3. 同步回调变得非常简单,因为您只需要使用when
  4. 我使用了jQuerys Deferreds,因为jsFiddle在下拉框中有jquery。您可以使用任何您想要的实现。

    当你实现它的概念时,你自己不应该太难。

答案 1 :(得分:2)

您可以使用真正意图处理问题的async.waterfall function。所有函数都是串行调用的,函数的结果作为参数发送到下一个函数。以下是文档中的示例用法:

async.waterfall([
    function(callback){
        callback(null, 'one', 'two');
    },
    function(arg1, arg2, callback){
        callback(null, 'three');
    },
    function(arg1, callback){
        // arg1 now equals 'three'
        callback(null, 'done');
    }
], function (err, result) {
   // result now equals 'done'    
});

答案 2 :(得分:0)

看看这段代码。

var i=0;
var length = data.id.length;
var getData = function(index)
{
    DAO.getUserById(data.id[index],function(err,resp1)
    {
        /* some other work based on resp1 */
        DAO.getOtherData(resp1.username,resp1.userId,function(err,resp2)
        {
             /* similary some other work*/
             index++;
             if(index < length)
             {
                getData(index);
             }
        });
   });
}
getData(i);

这是你需要的吗?