您的代码无法按预期运行的原因是,它实际上在做一些与您认为的有所不同的事情。
假设您有类似以下内容的东西:
stepOne().then(stepTwo, handleErrorOne).then(stepThree, handleErrorTwo).then(null, handleErrorThree);
为了更好地了解正在发生的事情,让我们假设这是带有
try/
catch块的同步代码:
try { try { try { var a = stepOne(); } catch(e1) { a = handleErrorOne(e1); } var b = stepTwo(a); } catch(e2) { b = handleErrorTwo(e2); } var c = stepThree(b);} catch(e3) { c = handleErrorThree(e3);}
的
onRejected处理程序(的第二个参数
then)本质上是一个纠错机制(如
catch块)。如果抛出错误
handleErrorOne,它将被下一个catch块(
catch(e2))捕获,依此类推。
这显然不是您想要的。
假设无论发生什么问题,我们都希望整个解决方案链失败:
stepOne().then(function(a) { return stepTwo(a).then(null, handleErrorTwo);}, handleErrorOne).then(function(b) { return stepThree(b).then(null, handleErrorThree);});
注意:我们可以保留
handleErrorOne它的位置,因为只有在
stepOne拒绝时才会调用它(它是链中的第一个函数,因此我们知道如果链在此刻被拒绝,那只能是由于该函数的诺言而已)
。
重要的变化是其他功能的错误处理程序不属于主要的Promise链。相反,每个步骤都有其自己的“子链”,
onRejected仅当该步骤被拒绝(但主链无法直接到达)时才调用该子链。
这样做的原因是
onFulfilled和
onRejected都是
then方法的可选参数。如果兑现了承诺(即已解决),并且
then链中的下一个没有
onFulfilled处理程序,则链将继续进行,直到有一个具有此类处理程序的处理程序为止。
这意味着以下两行是等效的:
stepOne().then(stepTwo, handleErrorOne)stepOne().then(null, handleErrorOne).then(stepTwo)
但是以下行 并不 等同于以上两行:
stepOne().then(stepTwo).then(null, handleErrorOne)
Angular的promise库
$q基于kriskowal的
Q库(具有更丰富的API,但是包含您可以在中找到的所有内容
$q)。GitHub上的Q的API文档可能证明是有用的。Q实现了Promises / A +规范,该规范详细介绍了如何
then以及如何正确地实现承诺解析行为。
编辑:
还要记住,如果您想打破错误处理程序中的链条,它需要返回被拒绝的承诺或抛出错误(将被捕获并自动包裹在被拒绝的承诺中)。如果您不返回承诺,
then则将返回值包装在为您解决的承诺中。
这意味着,如果您不返回任何内容,则实际上是在返回一个已解析的value承诺undefined
。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)