不理解javascript承诺反模式,从回调返回承诺
有人能解释一下为什么在承诺回调中返回承诺被认为是反模式的吗?显然,它打破了异常冒泡,但显然我对承诺的理解是缺乏的,因为我无法清楚地想象这将如何工作。我的反模式代码如下:不理解javascript承诺反模式,从回调返回承诺,javascript,promise,Javascript,Promise,有人能解释一下为什么在承诺回调中返回承诺被认为是反模式的吗?显然,它打破了异常冒泡,但显然我对承诺的理解是缺乏的,因为我无法清楚地想象这将如何工作。我的反模式代码如下: var a = new Promise(function (res, rej) { setTimeout(function () { res("timeout"); }, 1000); }); a.then(function (res) { console.log("a");
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);
});
编辑:
这个问题与我的一个朋友有关,我在那里做了一些类似的承诺,其中一个答案是:
“您还必须永远不要将回调与承诺混为一谈,因为这样您就失去了异常冒泡(承诺的意义)并使代码变得超级冗长。”
所以现在我真的很困惑它是否是反模式的,如果是,为什么 “您还必须永远不要将回调与承诺混为一谈,因为这样您就失去了异常冒泡(承诺的意义)并使代码变得超级冗长。”
Petka在这里的意思是,您不应该在用户代码中同时使用基于回调的方法和承诺,因为这将使您的代码非常冗长,如您的示例所示
这是冗长的,因为每次调用函数时都必须基于回调手动解析或拒绝新承诺
设置超时示例:超时完成后,必须手动调用解析器。 现在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);
}
});
})
在这里,您必须解决或拒绝,因为您将承诺与回调混合在一起,这将使您的代码非常脆弱和混乱
解决方案:
当您需要调用一个只支持回调的方法时,不要到处创建新的承诺,而是将基于回调的方法包装一次,然后在任何地方都使用它
var readFileAsync = new Promise(function (resolve, reject) {
fs.readFile('foo.txt', function (err, res) {
if (err){
reject(err);
return;
} else {
resolve(res);
}
});
});
奖金:
你甚至不需要把自己裹起来,蓝鸟已经把你盖住了。
结帐承诺就在这里:
整个解释有点偏离了这样一个事实,即在承诺的oncompleted
方法中返回承诺是完全有效的。
这是承诺/A+规范的一部分,请参见承诺解决程序->2.3.2如果x是承诺,则采用其状态[[3.4](#注释)]:
我认为你的困惑源于这样一个事实:佩特卡告诉你不要在你的例子中创造和回报新的承诺。但这与你正在回馈承诺这一事实无关,而是与你不应该在那个地方创造承诺这一事实有关,如上所述
使用包装版本,然后您可以在任何地方返回/链接它们。“您还必须永远不要将回调与承诺混合在一起,因为这样您就失去了异常冒泡(承诺的意义)并使代码变得超级冗长。”
Petka在这里的意思是,您不应该在用户代码中同时使用基于回调的方法和承诺,因为这将使您的代码非常冗长,如您的示例所示
这是冗长的,因为每次调用函数时都必须基于回调手动解析或拒绝新承诺
设置超时示例:
超时完成后,必须手动调用解析器。
现在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);
}
});
})
在这里,您必须解决或拒绝,因为您将承诺与回调混合在一起,这将使您的代码非常脆弱和混乱
解决方案:
当您需要调用一个只支持回调的方法时,不要到处创建新的承诺,而是将基于回调的方法包装一次,然后在任何地方都使用它
var readFileAsync = new Promise(function (resolve, reject) {
fs.readFile('foo.txt', function (err, res) {
if (err){
reject(err);
return;
} else {
resolve(res);
}
});
});
奖金:
你甚至不需要把自己裹起来,蓝鸟已经把你盖住了。
结帐承诺就在这里:
整个解释有点偏离了这样一个事实,即在承诺的oncompleted
方法中返回承诺是完全有效的。
这是承诺/A+规范的一部分,请参见承诺解决程序->2.3.2如果x是承诺,则采用其状态[[3.4](#注释)]:
我认为你的困惑源于这样一个事实:佩特卡告诉你不要在你的例子中创造和回报新的承诺。但这与你正在回馈承诺这一事实无关,而是与你不应该在那个地方创造承诺这一事实有关,如上所述
使用包装版本,然后您可以将它们返回/链接到任何您想要的地方。这不是反模式。您是在谈论延迟反模式吗@WillemD'Haeselleer我想不是。。延迟反模式是当您返回承诺或解决它时,即使您不必这样做。同样,我的理解可能不正确,请让我知道是否是这样。从处理程序返回承诺。然后()
处理程序就是如何使用承诺一个接一个地链接多个异步活动。这一概念没有任何模式。你能确定你在哪里看到这个你认为你正在使用的反模式吗?看来您对这个反模式的定义是错误的,所以唯一能澄清这一点的方法就是更具体地说明您认为反模式实际上是什么。@BenjaminGruenbaum:what,使用Promise
构造函数?我以为问题是关于从然后回调返回承诺。这不是反模式。你是说延迟反模式吗@WillemD'Haeselleer我想不是。。延迟反模式是当您返回承诺或解决它时,即使您不必这样做。再一次我的理解是mi