我可以用啥来替换嵌套的异步回调?
Posted
技术标签:
【中文标题】我可以用啥来替换嵌套的异步回调?【英文标题】: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 我对“排队”进行了一些搜索,但找不到任何我想要的东西。你有参考吗?
听起来像github.com/caolan/async#series
【参考方案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'
);
【讨论】:
以上是关于我可以用啥来替换嵌套的异步回调?的主要内容,如果未能解决你的问题,请参考以下文章