Javascript 在此之前和之后放置捕获
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42013104/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Placement of catch BEFORE and AFTER then
提问by Zanko
I have trouble understanding the difference between putting .catchBEFORE and AFTER then in a nested promise.
我无法理解将.catchBEFORE 和 AFTER 放在嵌套承诺中的区别。
Alternative 1:
备选方案 1:
test1Async(10).then((res) => {
return test2Async(22)
.then((res) => {
return test3Async(100);
}).catch((err) => {
throw "ERROR AFTER THEN";
});
}).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
});
Alternative 2:
备选方案 2:
test1Async(10).then((res) => {
return test2Async(22)
.catch((err) => {
throw "ERROR BEFORE THEN";
})
.then((res) => {
return test3Async(100);
});
}).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
});
The behavior of each function is as follow, test1 fail if number is <0test2 fails if number is > 10and test3 fails if number is not 100. In this case test2 is only failing.
每个函数的行为如下,如果数字是 test1 失败,如果数字是<0test2 失败,如果数字不是> 10,则 test3 失败100。在这种情况下,test2 只是失败了。
I tried to run and make test2Async fail, both BEFORE and AFTER then behaves the same way and that is not executing the test3Async. Can somebody explain to me the main difference for placing catch in different places?
我试图运行并使 test2Async 失败,然后 BEFORE 和 AFTER 的行为方式相同,并且没有执行 test3Async。有人可以向我解释在不同地方放置 catch 的主要区别吗?
In each function I console.log('Running test X')in order to check if it gets executed.
在每个函数中,我console.log('Running test X')为了检查它是否被执行。
This question arises because of the previous thread I posted How to turn nested callback into promise?. I figure it is a different problem and worth posting another topic.
出现这个问题是因为我之前发布的帖子如何将嵌套回调转换为承诺?. 我认为这是一个不同的问题,值得发布另一个主题。
回答by jfriend00
So, basically you're asking what is the difference between these two (where pis a promise created from some previous code):
所以,基本上你是在问这两者之间有什么区别(p从以前的代码创建的承诺在哪里):
return p.then(...).catch(...);
and
和
return p.catch(...).then(...);
There are differences either when p resolves or rejects, but whether those differences matter or not depends upon what the code inside the .then()or .catch()handlers does.
p 解决或拒绝时存在差异,但这些差异是否重要取决于.then()or.catch()处理程序中的代码做什么。
What happens when presolves:
p解决时会发生什么:
In the first scheme, when presolves, the .then()handler is called. If that .then()handler either returns a value or another promise that eventually resolves, then the .catch()handler is skipped. But, if the .then()handler either throws or returns a promise that eventually rejects, then the .catch()handler will execute for both a reject in the original promise p, but also an error that occurs in the .then()handler.
在第一个方案中,当p解析时,.then()处理程序被调用。如果该.then()处理程序返回一个值或另一个最终解决的承诺,.catch()则跳过该处理程序。但是,如果.then()处理程序抛出或返回一个最终拒绝的承诺,那么.catch()处理程序将执行原始承诺中的拒绝p,以及.then()处理程序中发生的错误。
In the second scheme, when presolves, the .then()handler is called. If that .then()handler either throws or returns a promise that eventually rejects, then the .catch()handler cannot catch that because it is before it in the chain.
在第二种方案中,当p解析时,.then()处理程序被调用。如果该.then()处理程序抛出或返回一个最终拒绝的承诺,则该.catch()处理程序无法捕获它,因为它在链中位于它之前。
So, that's difference #1. If the .catch()handler is AFTER, then it can also catch errors inside the .then()handler.
所以,这就是差异#1。如果.catch()处理程序在 AFTER 之后,那么它也可以捕获.then()处理程序内部的错误。
What happens when prejects:
p拒绝时会发生什么:
Now, in the first scheme, if the promise prejects, then the .then()handler is skipped and the .catch()handler will be called as you would expect. What you do in the .catch()handler determines what is returned as the final result. If you just return a value from the .catch()handler or return a promise that eventually resolves, then the promise chain switches to the resolved state because you "handled" the error and returned normally. If you throw or return a rejected promise in the .catch()handler, then the returned promise stays rejected.
现在,在第一个方案中,如果 Promisep拒绝,则.then()跳过.catch()处理程序并且将按预期调用处理程序。您在.catch()处理程序中执行的操作决定了作为最终结果返回的内容。如果您只是从.catch()处理程序返回一个值或返回一个最终解决的承诺,那么承诺链将切换到已解决状态,因为您“处理”了错误并正常返回。如果您在.catch()处理程序中抛出或返回被拒绝的承诺,则返回的承诺将保持被拒绝。
In the second scheme, if the promise prejects, then the .catch()handler is called. If you return a normal value or a promise that eventually resolves from the .catch()handler (thus "handling" the error), then the promise chain switches to the resolved state and the .then()handler after the .catch()will be called.
在第二种方案中,如果承诺p拒绝,则.catch()调用处理程序。如果您返回一个正常值或最终从.catch()处理程序解析的承诺(从而“处理”错误),那么承诺链将切换到已解析状态,并且将调用.then()之后的处理程序.catch()。
So that's difference #2. If the .catch()handler is BEFORE, then it can handle the error and allow the .then()handler to still get called.
这就是区别#2。如果.catch()处理程序是 BEFORE,那么它可以处理错误并允许.then()处理程序仍然被调用。
When to use which:
何时使用哪个:
Use the first scheme if you want just one .catch()handler that can catch errors in either the original promise por in the .then()handler and a reject from pshould skip the .then()handler.
如果您只需要一个.catch()可以在原始承诺p或处理程序中捕获错误的.then()处理程序,并且拒绝来自p应该跳过.then()处理程序,请使用第一种方案。
Use the second scheme if you want to be able to catch errors in the original promise pand maybe (depending upon conditions), allow the promise chain to continue as resolved, thus executing the .then()handler.
如果您希望能够捕获原始承诺中的错误,p并且可能(取决于条件)允许承诺链继续解决,从而执行.then()处理程序,请使用第二种方案。
The other option
另一种选择
There's one other option to use both callbacks that you can pass to .then()as in:
还有另一个选项可以使用您可以传递给的两个回调,.then()如下所示:
p.then(fn1, fn2)
This guarantees that only one of fn1or fn2will ever be called. If presolves, then fn1will be called. If prejects, then fn2will be called. No change of outcome in fn1can ever make fn2get called or vice versa. So, if you want to make absolutely sure that only one of your two handlers is called regardless of what happens in the handlers themselves then you can use p.then(fn1, fn2).
这保证只有其中之一fn1或fn2将永远被调用。如果p解决,fn1则将被调用。如果p拒绝,fn2则将被调用。任何结果的变化都不fn1能使fn2被调用,反之亦然。因此,如果您想绝对确保只调用两个处理程序中的一个,而不管处理程序本身发生什么,那么您可以使用p.then(fn1, fn2).
回答by akivajgordon
jfriend00's answeris excellent, but I thought it would be a good idea to add the analogous synchronous code.
jfriend00 的回答很好,但我认为添加类似的同步代码是个好主意。
return p.then(...).catch(...);
is similar to the synchronous:
类似于同步:
try {
iMightThrow() // like `p`
then()
} catch (err) {
handleCatch()
}
If iMightThrow()doesn't throw, then()will be called. If it does throw (or if then()itself throws), then handleCatch()will be called. Notice how the catchblock has no control over whether or not thenis called.
如果iMightThrow()不抛出,then()将被调用。如果它确实抛出(或者如果then()它本身抛出),handleCatch()则将被调用。请注意该catch块如何无法控制是否then被调用。
On the other hand,
另一方面,
return p.catch(...).then(...);
is similar to the synchronous:
类似于同步:
try {
iMightThrow()
} catch (err) {
handleCatch()
}
then()
In this case, if iMightThrow()doesn't throw, then then()will execute. If it does throw, then it would be up to handleCatch()to decide if then()is called, because if handleCatch()rethrows, then then()will not be called, since the exception will be thrown to the caller immediately. If handleCatch()can gracefully handle the issue, then then()will be called.
在这种情况下,如果iMightThrow()不抛出,then()则将执行。如果确实抛出,则由handleCatch()决定是否then()调用,因为如果handleCatch()重新抛出,则then()不会被调用,因为异常将立即抛出给调用者。如果handleCatch()可以优雅地处理问题,那么then()将被调用。

