我正在使用 Q nodejs 中的库并且过去没有太多地使用 promises,但是我有需要大量嵌套的半复杂逻辑并且认为 Q 将是一个很好的解决方案,但是我发现它似乎与只是“回调 hell ”。
基本上我说了 5 种方法,所有这些方法都需要来自前一个或前一个的数据。这是一个例子:
我们从一些二进制数据开始,这些数据具有基于二进制生成的 sha1 哈希。
var data = {
hash : "XXX"
, binary: ''
}
首先我们想看看我们是否已经有了这个,使用这个方法:
findItemByHash(哈希)
如果我们没有它,我们需要保存它,使用:
保存项目(哈希)
现在我们需要将其关联到用户,而不仅仅是保存的结果。现在我们关联了一个更大的层次结构,所以我们需要首先得到它,做:
getItemHierarchy(item_id)
,我们使用从之前的 saveItem
item_id
现在,我们可以将这些结果“复制”给用户:
saveUserHierarchy(层次结构)
现在我们已经完成了,但是,这假设该项目还不存在。所以我们需要处理项目确实存在的情况。这将是:
我们需要检查用户是否可能有这个:
getUserItemByItemId(item_id)
- item_id 是从 findItemByHash
如果它存在,我们就完成了。
如果没有:
getItemHierarchy(item_id)
然后
saveUserHierarchy(层次结构)
好的,现在我们有执行这些检查的回调,这很好。但是我们需要一路处理每种情况下的错误。这也很好,只是增加了困惑。实际上,如果流程的任何部分抛出错误或拒绝,那么它可以停止并在一个地方处理它。
现在有了 Q,我们可以做这样的事情:
findItemByHash(hash).then(function(res) {
if (!res) {
return saveItem(hash).then(function(item) {
return getItemHierarchy(item.id).then(function(hierarchy) {
return saveUserHierarchy(hierarchy);
});
})
} else {
return getUserItemByItemId(res.id).then(function(user_item) {
if (user_item) {
return user_item;
}
return getItemHierarchy(res.id).then(function(hierarchy) {
return saveUserHierarchy(hierarchy);
});
});
}
})
//I think this will only handle the reject for findItemByHash?
.fail(function(err) {
console.log(err);
})
.done();
所以,我想我的问题是这样的。在 Q 中有更好的方法来处理这个问题吗?
谢谢!
最佳答案
我喜欢 promises 的原因之一是处理错误非常容易。在您的情况下,如果这些 promise 中的任何一个失败,它将在您定义的失败子句中被捕获。如果您想当场处理它们,您可以指定更多的fail
子句,但这不是必需的。
举个简单的例子,有时我想处理错误并返回其他内容,而不是传递错误。我会做这样的事情:
function awesomeFunction() {
var fooPromise = getFoo().then(function() {
return 'foo';
}).fail(function(reason) {
// handle the error HERE, return the string 'bar'
return 'bar';
});
return fooPromise;
}
awesomeFunction().then(function(result) {
// `result` will either be "foo" or "bar" depending on if the `getFoo()`
// call was successful or not inside of `awesomeFunction()`
})
.fail(function(reason) {
// This will never be called even if the `getFoo()` function fails
// because we've handled it above.
});
现在关于您关于摆脱“返回 hell ”的问题 - 只要下一个函数不需要有关前一个函数的信息,您就可以链接 .then
子句而不是嵌套它们:
doThis().then(function(foo) {
return thenThis(foo.id).then(function(bar) {
// `thenThat()` doesn't need to know anything about the variable
// `foo` - it only cares about `bar` meaning we can unnest it.
return thenThat(bar.id);
});
});
// same as the above
doThis().then(function(foo) {
return thenThis(foo.id);
}).then(function(bar) {
return thenThat(bar.id);
});
为了进一步减少它,创建组合重复 promise 组合的函数,我们剩下:
function getItemHierarchyAndSave(item) {
return getItemHierarchy(item.id).then(function(hierarchy) {
return saveUserHierarchy(hierarchy);
});
}
findItemByHash(hash).then(function(resItem) {
if (!resItem) {
return saveItem(hash).then(function(savedItem) {
return getItemHierarchyAndSave(savedItem);
});
}
return getUserItemByItemId(resItem.id).then(function(userItem) {
return userItem || getItemHierarchyAndSave(resItem);
});
})
.fail(function(err) { console.log(err); })
.done();
免责声明:我不使用 Q promise ,我更喜欢 when
promises主要是因为它附带的额外好处,但原理是相同的。
关于node.js - 使用 Q/promises 与回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20430562/