我可以用什么来取代嵌套的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 。