【问题标题】:What can I use to replace nested async callbacks?我可以用什么来替换嵌套的异步回调?
【发布时间】:2012-12-18 11:10:25
【问题描述】:

假设我想发送一封电子邮件然后更新数据库,这两个操作都是异步的。这就是我通常的写法。

send_email(function(err, id){
    if(err){
        console.log("error");
    }else{
        update_database(id,function(err, id){
            if(err){
                console.log("error");
            }else{
                console.log("success");
            }
        });
    }
});

我想用中间件来代替。

var mid = {};

mid.send_email = function(){
    return function(next){
        send_email(function(err,id){
            if(err){
                console.log("error");
            }else{
                next(id);
            }
        });
    }
}

mid.update_database = function(){
    return function(id,next){
        update_database(id,function(err,id){
            if(err){
                console.log("error");
            }else{
                next(id);
            }
        });
    }
}

mid.success = function(){
    return function(id,next){
        console.log("success")
        next(id);
    }   
}

堆叠中间件。

middleware.use(mid.send_email());
middleware.use(mid.update_database());
middleware.use(mid.success());

手头有两个主要问题。

  • 如何使用中间件代替嵌套回调?
  • 是否可以将变量传递给next()

【问题讨论】:

  • 这叫“排队”
  • 尚不清楚您帖子中的“中间件”是指某个特定的库还是“有助于...的库”。标签“中间件”肯定没有特定于 JavaScript 的内容。
  • @AlexeiLevenkov 我明白你的意思。我使用了middleware 这个词,因为这就是技术。但我也不确定是否有图书馆。
  • @zzzzBov 我对“排队”进行了一些搜索,但找不到任何我想要的东西。你有参考吗?

标签: javascript node.js asynchronous callback middleware


【解决方案1】:

我在工作中一直使用Queue.js

【讨论】:

    【解决方案2】:

    您最好使用CommonJS module.exports

    你可以像这样创建一个文件:

    module.exports = function (){
        function sendEmail(doneCallback){
            // do your stuff, then when you are done:
            if(!err){
                doneCallback(whatever,args,you,need);
            }
        }
    
        function updateDB(success){
            // do your stuff, then when you are done:
            success(whatever,args,you,need);
        }
    
        return {
            send: sendEmail,
            update: updateDB
        };
    };
    

    然后在你的server.js:

    var lib = require('./mylib.js');
    
    lib.send(function(result){
       console.log(result);
    });
    

    这是一个类似的模式,它可能会让你更好地理解我的意思。它由库组成,烘焙 function 并将其传递给需要链接的任何人,如下所示(更实际的示例,这次是客户端):

    ui.bistate($('#mybutton'), function(restore){
        $.ajax({
            url: '/api/1.0/catfood',
            type: 'PUT',
            data: {
                catfood: {
                    price: 1.23,
                    name: 'cheap',
                    text: 'Catzy'
                }
            }
        }).done(function(res){
            // stuff with res
            restore();
        });
    });
    

    在库中,restore 是这样提供的:

    var ui = function(){
        function bistate(button, action) {
            var originalText = buttonText.data('text'),
                disabledText = buttonText.data('text-disabled');
    
            function restore(){
                button.prop('disabled', false);
                button.text(originalText);
            }
    
            function disable(){
                button.prop('disabled', true);
                button.text(disabledText);
            }
    
            button.on('click', function(){
                disable();
                action(restore);
            });
            restore();
        }
    
        return {
            bistate: bistate
        };
    }();
    

    允许消费者在想要恢复按钮时控制流程,并让库不必处理消费者想要在两者之间执行异步操作的复杂情况。

    总的来说,要点是:来回传递回调是巨大的,并且没有使用足够广泛

    【讨论】:

      【解决方案3】:

      您想要的是能够处理异步控制流。很多 js 库可以帮助你实现这一点。您可以尝试 Async 库和 waterfall 函数,因为您希望能够将变量传递给将要执行的下一个函数:

      https://github.com/caolan/async#waterfall

      "连续运行一个函数数组,每个函数将其结果传递给数组中的下一个。但是,如果任何函数将错误传递给回调,则不会执行下一个函数并立即调用主回调有错误。”

      例子:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-21
        • 1970-01-01
        • 2012-07-15
        • 1970-01-01
        • 2017-09-17
        相关资源
        最近更新 更多