有人可以向我解释为什么在承诺回调中返回承诺会被视为反模式吗?显然它打破了异常冒泡,但显然我对承诺的理解是缺乏的,因为我无法清楚地描述如何工作。我的反模式代码如下:
var a = new Promise(function (res, rej) {
setTimeout(function () {
res("timeout");
}, 1000);
});
a.then(function (res) {
console.log("a");
console.log(res);
return new Promise(function (res, rej) {
console.log("b");
setTimeout(function () {
res("timeout2");
}, 2000);
}).then(function (res) {
console.log("c");
console.log(res);
}).then(function (res) {
console.log("d");
console.log(res);
}, function (res) {
console.log("e");
console.log(res);
});
}).then(function (res) {
console.log("l");
console.log(res);
});
编辑:
这个问题与我的previous questions之一有关,我在其中做了类似承诺的事情,其中一个答案说:
"你也必须永远不要将回调与promises混合,因为这样你就会失去异常冒泡(承诺点)并使你的代码变得非常冗长。"
所以现在我真的很困惑,如果它是反模式,如果是这样的话。
答案 0 :(得分:4)
“你也必须永远不要将回调与promises混合在一起,因为这样你就会失去异常冒泡(承诺点)并使你的代码变得非常冗长。”
Petka在这里的意思是,你不应该在你的用户代码中使用基于回调的方法和Promises,因为这会使你的代码非常冗长,如你的例子所示。
这很冗长,因为每次调用函数时都必须根据回调手动解析或拒绝新的Promise。
setTimeout示例:
超时完成后,您必须手动调用解析程序。
现在setTimeout是一个很糟糕的例子,因为它没有可能拒绝它的操作。
return new Promise(function (resolve, reject) {
console.log("b");
setTimeout(function () {
resolve("timeout2");
}, 2000);
})
更好的例子
假设你想这样打fs.readFile
:
return new Promise(function (resolve, reject) {
fs.readFile('foo.txt', function (err, res) {
if (err){
reject(err);
return;
} else {
resolve(res);
}
});
})
在这里你必须解决或拒绝,因为你将promises与回调混合,这将使你的代码变得非常脆弱和混乱。
<强>解决方案:强>
当您需要调用仅支持回调的方法时,不要在整个地方创建新的Promise,而是将基于回调的方法包装一次并在任何地方使用它。
var readFileAsync = new Promise(function (resolve, reject) {
fs.readFile('foo.txt', function (err, res) {
if (err){
reject(err);
return;
} else {
resolve(res);
}
});
});
<强>加成:强>
你甚至不需要这样做包裹你的自己,蓝鸟已经让你满意。 结账宣传就在这里:
https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification
除了在promise的onFulfilled
方法中返回Promise完全有效之外,这个整体解释也是如此。
这是Promise / A +规范的一部分,请参阅The Promise Resolution Procedure
- &gt; 2.3.2 If x is a promise, adopt its state [[3.4](#notes)]:
我认为你的困惑源于Petka告诉你不要在你的例子中创造并返回新的承诺。但这与你回归Promise的事实无关,而是与你不应该在那个地方创造承诺的事实有关,如上所述。
使用包装版本,然后您可以在任何地方返回/链接它们。