在之前和之后放置捕获物
我很难理解把.catch(function(err)BEFORE和AFTER then在嵌套promise中的区别。
test1Async(10).then(function (lol) { return test2Async(22) .then(function (lol) { return test3Async(100); }).catch(function (err) { throw "ERROR AFTER THEN"; }); }).then(function (results) { console.log(results); }).catch(function (err) { console.log(err); });
和这个
test1Async(10).then(function (lol) { return test2Async(22) .catch(function (err) { throw "ERROR BEFORE THEN"; }) .then(function (lol) { return test3Async(100); }); }).then(function (results) { console.log(results); }).catch(function (err) { console.log(err); });
每个函数的行为如下,如果number <0
,则test1失败,如果number > 10
,则test2失败;如果number不是100
,则test3失败。 在这种情况下,test2只是失败。
我试图运行,并使test2Async失败,BEFORE和AFTER,然后行为相同的方式,而不是执行test3Async。 有人可以向我解释在不同的地方摆放渔获物的主要区别吗?
在每个函数我console.log(运行testingX),以检查是否得到执行。
这个问题出现是因为我之前的线程发布如何将嵌套的callback变成诺言? 。 我认为这是一个不同的问题,值得发表另一个话题。
所以,基本上你问这两者之间有什么区别(其中p
是从以前的代码中创build的一个承诺):
return p.then(...).catch(...);
和
return p.catch(...).then(...);
当pparsing或拒绝时,有差异,但是这些差异是否重要取决于.catch()
或.catch()
处理程序中的代码是做什么的。
p
parsing时会发生什么:
在第一个scheme中,当p
parsing时,调用.then()
处理程序。 如果.then()
处理程序返回一个值或另一个最终解决的promise,则跳过.catch()
处理程序。 但是,如果.then()
处理程序抛出或返回一个最终拒绝的promise,那么.catch()
处理程序将执行原始promise中的拒绝,而且.then()
处理程序。
在第二个scheme中,当p
parsing时,调用.then()
处理程序。 如果.then()
处理程序抛出或返回最终拒绝的承诺,那么.catch()
处理程序无法捕获,因为它在链中。
所以,这是差异#1。 如果.catch()
处理程序是AFTER,那么它也可以捕获.catch()
处理程序中的错误。
当拒绝时会发生什么:
现在,在第一个scheme中,如果promise拒绝,那么.catch()
处理程序将被跳过, .catch()
处理程序将按照您的预期调用。 你在.catch()
处理程序中所做的决定了最终结果返回的内容。 如果您只是从.catch()
处理程序返回值或返回最终解决的承诺,那么承诺链将切换到已解决的状态,因为您“处理”了错误并正常返回。 如果您在.catch()
处理程序中抛出或返回被拒绝的承诺,则返回的承诺将保持拒绝状态。
在第二种scheme中,如果承诺p
拒绝,则.catch()
处理程序。 如果你返回一个普通的值或者一个最终从.catch()
处理程序parsing出来的.catch()
从而“处理”错误),那么promise链在.catch()
之后切换到parsing状态和.catch()
将被调用。
所以这是差异#2。 如果.catch()
处理程序是BEFORE,那么它可以处理该错误并允许.then()
处理程序仍然被调用。
何时使用哪个:
如果只需要一个.catch()
处理程序,可以捕获原始的promise p
或.catch()
处理程序中的错误,并且来自p
的拒绝应该跳过.catch()
处理程序,请使用第一个scheme。
使用第二个scheme,如果你想能够捕获原始的承诺p
中的错误,也许(取决于条件),允许承诺链继续解决,从而执行.then()
处理程序。
另一种select
还有一个选项可以使用这两个callback,你可以传递给.then()
如下所示:
p.then(fn1, fn2)
这保证了fn1
或fn2
中只有一个被调用。 如果p
parsing,那么fn1
将被调用。 如果p
拒绝,那么fn2
将被调用。 fn1
的结果没有任何变化可以使得fn2
被调用,反之亦然。 所以,如果你想确保只有你的两个处理程序中的一个被调用,而不pipe在处理程序本身中发生了什么,那么你可以使用p.then(fn1, fn2)
。
jfriend00的答案非常好,但是我认为添加类似的同步代码是个好主意。
return p.then(...).catch(...);
类似于同步:
try { iMightThrow() // like `p` then() } catch (err) { handleCatch() }
如果iMightThrow()
不抛出, then()
将被调用。 如果它抛出(或如果then()
本身抛出),然后handleCatch()
将被调用。 请注意catch
块是否无法控制是否被调用。
另一方面,
return p.catch(...).then(...);
类似于同步:
try { iMightThrow() } catch (err) { handleCatch() } then()
在这种情况下,如果iMightThrow()
不抛出,那么将执行then()
。 如果抛出, handleCatch()
决定是否调用了then()
,因为如果handleCatch()
抛出,则不会调用then()
,因为exception将立即抛出给调用者。 如果handleCatch()
可以优雅地处理这个问题, then()
将被调用。