我想知道在JavaScript中处理异步代码时哪两个方法更好。我想了解哪种方法可以实现更清晰的代码。我使用了promises,它们似乎比异步方法(https://github.com/caolan/async)更灵活。
我也知道Task.js库(http://taskjs.org/),但这依赖于yield关键字,它是Ecmascript Harmony的一部分。
答案 0 :(得分:11)
async
库封装了一些非常常见的异步模式,包括并行进行任意异步调用并异步迭代列表。它设计用于“nodeback”(err, res)
API,这使得它对许多Node.js应用程序很有用。 async
是特定的解决方案,它只会简化库中包含的异步模式。
async
封装的问题可以更简单地解决。
我将通过快速浏览一些async
的可用模式来演示这一点。例如,async.waterfall
函数的用法如下:
async.waterfall([
function (cb) {
asyncCall('argument', cb);
},
function(resultOfFirstCall, cb) {
anotherCall(resultOfFirstCall, 'someOtherArgument' cb);
},
], function(err, res) {
if (err) handle(err);
useFinalResult(res);
});
在大多数promise库中没有等同于async.waterfall
(或者至少Q中没有一个),因为这么简单使用{{1}从头开始实现它},就像这样(基于Q的示例,但在其他promise库上几乎相同):
Array.reduce
[
function() {
return asyncCall('argument');
},
function(resultOfFirstCall) {
return anotherCall(resultOfFirstCall, 'someOtherArgument');
}
].reduce(Q.when, Q())
.then(useFinalResult, handle);
中的其他重要功能包括async
,其中Q包含为async.parallel
:
Q.all
// async
async.parallel([
asyncFunc,
asyncFunc2
], function(err, res) {
if (err) handle(err);
useFinalResult(res);
// res[0] === asyncFuncResult
// res[1] === asyncFunc2Result
});
// Q
Q.all([
asyncFunc(),
asyncFunc2()
]).then(useFinalResult, handle);
。当你使用promises时,你实际上不需要 async.map
,因为正常async.map
就足够了:
Array.map
// async
async.map(['file', 'file2', 'file3'], fs.stat, function(err, res) {
if (err) handle(err);
useFinalResult(res);
});
// Q
Q.all(['file', 'file2', 'file3']
.map(Q.nfbind(fs.stat)))
.then(useFinalResult, handle);
的其余部分同样易于使用您的promise库中相对简单的部分简洁地实现。 (注意,最后一个示例使用函数async
:Q.nfbind
和Q提供的其他nfbind
函数基本上只需要使用带有nodeback API的promises,因此甚至没有特别大的阻抗试图将promises用于期望节点返回的库。)
最后,您是否使用promises或nodebacks取决于您,但我认为promises是一种更加灵活,功能强大且通常简洁的方法来实现大多数异步操作。
Callbacks are imperative, promises are functional值得一读,以获取更多信息。
答案 1 :(得分:3)
由于您使用节点标记了您的问题,我建议使用异步库。控制流功能非常适合处理并消除丑陋且难以遵循的回调链。 API设置非常适合将遵循节点签名(error, result)
的回调注入控制功能。它基本上包含在我编写的几乎所有节点脚本中。
虽然您也可以在客户端使用async,但对于大多数项目来说可能是不必要的。 jQuery包含promises,你可以用它们完成同样的事情。
答案 2 :(得分:1)
我认为promise / a和async lib具有差异目标,承诺专注于一步异步操作进度,异步专注于多步异步操作,对于节点,async对于大量异步apis使用更为狂野。
顺便说一句,要处理异步操作,使用命名函数代替匿名函数将是最有效的方法答案 3 :(得分:0)
gumballhead推荐 async.js ,但如果你正在使用Node,那么 i 会建议使用Parse Cloud Code。他们的API与其他好东西(如数据库)一起构建了承诺。它节省了时间,您不必担心后端稳定性。您可以将module.exports
稍加调整到exports
包含任何NPM模块。它还与您的前端无缝集成!在我目前的项目中,我一直在使用这种方法取得成功,并且只想用新方法发表评论。
您可以不使用Cloud Code,以及/何时/ 使用Cloud Code时,可以随意评论。因为我还没有这样的经历。