Ste*_*n G 5 javascript error-handling promise ecmascript-6
我从 E6 Promises 开始。我非常喜欢它们,但有一个关于错误处理的重要概念,我不明白,希望得到一些澄清。
让我们假设以下简单的函数返回一个承诺:
function promiseString(str, timeout, doResolve) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (doResolve) {
resolve(str);
} else {
reject(new Error("Rejecting " + str));
}
}, timeout);
});
}
Run Code Online (Sandbox Code Playgroud)
它非常简单,只为传递给它的字符串返回一个承诺,并导致该承诺在“超时”毫秒内被解析或拒绝(基于第三个参数)。
我可以按预期完全消耗它,如下所示:
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));
Run Code Online (Sandbox Code Playgroud)
如果在此链中的任何调用中将第三个参数从“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));
});
}
Run Code Online (Sandbox Code Playgroud)
想象一下,现在我按如下方式使用此代码,一切都在解决,没有任何拒绝,(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));
Run Code Online (Sandbox Code Playgroud)
正如所料,我在控制台中看到以下内容:
双重承诺:大承诺
但是,现在我更改了使用代码,将 doResolve 设置为“false”(这会导致我的承诺例程拒绝):
var dp = new DoublePromiser("Big", "Promise", false);
dp.promise
.then((s) => console.log("DoublePromise: " + s))
.catch((err)=>console.log("I did catch: ", err.message));
Run Code Online (Sandbox Code Playgroud)
由于我对错误应该如何“冒泡”的理解,我希望控制台记录如下:
我确实抓住了:拒绝大
但事实并非如此。相反,控制台显示一个未捕获的错误:
未捕获(承诺)错误:拒绝大
如果我在 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
});
}
Run Code Online (Sandbox Code Playgroud)
现在我得到了我的期望,错误并非没有被发现。但这似乎与错误冒泡的整个想法背道而驰,捕获错误只是为了重新拒绝相同的错误似乎很奇怪。
我错过了让这个简单地工作的方法吗?
我是否缺少一些基本概念?
您正在使用承诺构造函数反模式。不要将现有的承诺包装在你自己做出的另一个承诺中,因为这只会让你做很多额外的工作来使事情正常工作,而且由于大多数人没有正确地做这些额外的工作,它也很容易出现编程错误。只需返回您已经拥有的承诺。
改变这个:
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
});
}
Run Code Online (Sandbox Code Playgroud)
对此:
function DoublePromiser(str1, str2, doResolve) {
return promiseString(str1, 100, doResolve)
.then((s1) => promiseString(s1 + str2, 100, doResolve));
}
Run Code Online (Sandbox Code Playgroud)
然后,只需将其用作函数:
DoublePromiser("Big", "Promise", false).then(...);
Run Code Online (Sandbox Code Playgroud)
回顾:您几乎总是希望从.then()处理程序内部返回内部承诺,因为这允许嵌套错误向上传播,并且还可以正确地链接/序列异步操作。
而且,您几乎总是希望避免在现有承诺周围包装新承诺,因为您可以直接链接和/或返回现有的承诺。
另外,请注意,如果您执行 a .catch(),它将“处理”一个被拒绝的承诺并返回一个新的未拒绝的承诺,从那里继续承诺链,除非在.catch()处理程序内部您返回一个被拒绝的承诺或抛出异常。所以这:
p.catch((err) => console.log(err)).then(() => console.log("chain continues"))
Run Code Online (Sandbox Code Playgroud)
将愉快地执行这两个console.log()语句,因为.catch()“处理”了承诺,因此承诺链愉快地继续。
正如我在之前的评论中所说,如果没有 20 页的关于 Promise 如何工作的教程,这些 100% 的理论讨论很难达到你真正想要完成的目标(我们必须猜测真正的问题是什么)。东西。如果你发布一个你试图用这种技术解决的现实问题,那就更好了,我们可以用几行代码和几段解释来展示/解释最好的方法。
| 归档时间: |
|
| 查看次数: |
2844 次 |
| 最近记录: |