我可以用什么来取代嵌套的asynchronouscallback?

比方说,我想发送一封电子邮件,然后更新数据库,这两个行动是asynchronous的。 这是我通常会写的。

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()); 

手头有两个主要问题。

  • 我如何使用中间件代替嵌套的callback?
  • 是否有可能将variables传递给next()

你想要的是能够处理asynchronous控制stream程。 js库的很多可以帮助你实现这一点。 您可以尝试使用waterfall函数的Async库,因为您希望能够将variables传递给将要执行的下一个函数:

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

“按顺序运行一系列函数,每个函数都将结果传递给数组中的下一个函数,但是,如果任何函数将错误传递给callback函数,则不执行下一个函数,并立即调用主callback函数“。

例如:

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

你可能最好使用CommonJS module.exports

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

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

允许消费者在他想要恢复button时控制stream,并且重新处理消费者希望在其间执行asynchronous操作的复杂情况的库。

总的来说,重点在于:来回传递巨大且不够广泛

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