【发布时间】:2016-12-02 04:29:34
【问题描述】:
我从 E6 Promises 开始。我非常喜欢它们,但有一个关于错误处理的关键概念,我不明白,希望得到澄清。
让我们假设以下简单的函数返回一个承诺:
function promiseString(str, timeout, doResolve) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (doResolve) {
resolve(str);
} else {
reject(new Error("Rejecting " + str));
}
}, timeout);
});
}
这很简单,只是为传递给它的字符串返回一个承诺,并导致该承诺在“超时”毫秒内被解析或拒绝(基于第三个参数)。
我可以完全按照预期使用它,如下所示:
promiseString("One", 100, true)
.then((str) => { console.log("First then is " + str); return promiseString(str + " two", 100, true); })
.then((str) => { console.log("Second then is " + str); return promiseString(str + " three", 100, true); })
.then((str) => console.log(str))
.catch((err) => console.error(err));
如果在此链中的任何调用中将第三个参数从“true”更改为“false”,我的错误将按预期被捕获并发送到 console.error()。
但是,现在想象一下用于构造有前途的对象的以下(同样愚蠢的)函数:
function DoublePromiser(str1, str2, doResolve) {
this.promise = new Promise((resolve, reject) => {
promiseString(str1, 100, doResolve)
.then((s1) => promiseString(s1 + str2, 100, doResolve))
.then((s2) => resolve(s2));
});
}
现在想象一下,我按如下方式使用这段代码,一切都解决了,没有任何拒绝,(doResolve 设置为 true):
var dp = new DoublePromiser("Big", "Promise", true);
dp.promise
.then((s) => console.log("DoublePromise: " + s))
.catch((err)=>console.log("I did catch: ", err.message));
正如所料,我在控制台中看到以下内容:
双重承诺:大承诺
但是,现在我更改了消费代码,将 doResolve 设置为“false”(这会导致我的 promise 例程被拒绝):
var dp = new DoublePromiser("Big", "Promise", false);
dp.promise
.then((s) => console.log("DoublePromise: " + s))
.catch((err)=>console.log("I did catch: ", err.message));
由于我对错误应该如何“冒泡”的理解,我希望控制台记录如下:
我确实抓住了:拒绝大
但事实并非如此。相反,控制台显示一个未捕获的错误:
未捕获(承诺)错误:拒绝大
如果我在 DoublePromiser 的链末尾添加一个捕获,我只会得到我期望(和渴望)的结果,如下所示:
function DoublePromiser(str1, str2, doResolve) {
this.promise = new Promise((resolve, reject) => {
promiseString(str1, 100, doResolve)
.then((s1) => promiseString(s1 + str2, 100, doResolve))
.then((s2) => resolve(s2))
.catch((err) => reject(err)); // ADDING THIS TO MAKE IT WORK
});
}
现在我得到了我的期望,错误并非没有被发现。但这似乎与错误冒泡的整个想法背道而驰,并且为了重新拒绝相同的错误而捕获错误似乎很奇怪。
我是否错过了一种让它简单地工作的方法?
我是否遗漏了一些基本概念?
【问题讨论】:
-
这些 100% 的理论问题使用虚构的代码,并没有说明真正的问题,只是在堆栈溢出问题上效果不佳。
-
另外,您正在使用 promise 构造函数反模式:github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns
-
@estus - 我编辑了他们的标题。
-
@jfriend00 谢谢。顺便说一句,很好的答案,它确定了这一点。
-
重新打开,因为尽管其他答案包含可用于回答此问题的信息,但它们甚至与同一个实际问题都不接近。读过其他标题或问题的人不会认为这与这个问题是同一个问题。
标签: javascript error-handling promise ecmascript-6