【发布时间】:2014-04-24 23:33:15
【问题描述】:
我在一个项目(网络爬虫/人类活动模拟器)中使用了kriskowal's Q library,并且熟悉了 Promise、返回和解析/拒绝它们,以及库的基本异步控制流方法和错误抛出/捕获机制已被证明是必不可少的。
虽然我遇到了一些问题。我的promise.then 电话和我的回调具有形成金字塔的不可思议的趋势。有时是为了范围的原因,有时是为了保证一定的事件顺序。 (我想我也许可以通过重构来解决其中的一些问题,但接下来我想完全避免“回调地狱”。)
此外,调试非常令人沮丧。我花了很多时间console.log-寻找错误和错误的来源;在我终于找到它们之后,我会开始在那里抛出错误并使用promise.finally 在其他地方捕获它们,但是首先定位错误的过程是艰巨的。
另外,在我的项目中,订单很重要。我需要按顺序做几乎所有事情。很多时候我发现自己会生成返回 promise 的函数数组,然后使用 Array.prototype.reduce 将它们相互链接起来,我认为我不应该这样做。
以下是我使用这种缩减技术的方法之一的示例:
removeItem: function (itemId) {
var removeRegexp = new RegExp('\\/stock\\.php\\?remove=' + itemId);
return this.getPage('/stock.php')
.then(function (webpage) {
var
pageCount = 5,
promiseFunctions = [],
promiseSequence;
// Create an array of promise-yielding functions that can run sequentially.
_.times(pageCount, function (i) {
var promiseFunction = function () {
var
promise,
path;
if (i === 0) {
promise = Q(webpage);
} else {
path = '/stock.php?p=' + i;
promise = this.getPage(path);
}
return promise.then(function (webpage) {
var
removeMatch = webpage.match(removeRegexp),
removePath;
if (removeMatch !== null) {
removePath = removeitemMatch[0];
return this.getPage(removePath)
.delay(1000)
// Stop calling subsequent promises.
.thenResolve(true);
}
// Don't stop calling subsequent promises.
return false;
}.bind(this));
}.bind(this);
promiseFunctions.push(promiseFunction);
}, this);
// Resolve the promises sequentially but stop early if the item is found.
promiseSequence = promiseFunctions.reduce(function (soFar, promiseFunction, index) {
return soFar.then(function (stop) {
if (stop) {
return true;
} else {
return Q.delay(1000).then(promiseFunction);
}
});
}, Q());
return promiseSequence;
}.bind(this))
.fail(function (onRejected) {
console.log(onRejected);
});
},
我还有其他方法可以做基本相同的事情,但会遇到更严重的压痕问题。
我正在考虑使用coalan's async library 重构我的项目。它似乎与 Q 相似,但我想确切地知道它们有何不同。我得到的印象是 async 更“以回调为中心”,而 Q 是“以承诺为中心”。
问题:考虑到我的问题和项目要求,使用 async over Q 会获得什么和/或失去什么?图书馆如何比较? (特别是在顺序执行一系列任务和调试/错误处理方面?)
【问题讨论】:
-
要求顺序执行似乎抵消了异步的大部分好处。
-
如果你展示了一段你现在正在使用的特别笨拙的代码,而你想要一个更好的解决方案,人们可能会为你提供更好的建议。抽象地讨论不同库的优缺点或如何使用这些库要困难得多。
-
@jfriend00 我同意;我添加了一个代码示例。
-
可以通过正确使用 .then 来减少/移除“金字塔”。另一方面,异步库有几种方法可用于同步进行异步调用,例如
.series和.eachSeries。 .then 链当然可以实现同样的目标 -
@Robert Harvey - 在节点中,异步仍然很有价值,因为它为其他请求提供了处理的机会
标签: javascript node.js asynchronous q