您的代码无法按预期工作的原因是它实际上在做与您认为的有所不同的事情。
假设您有以下内容:
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条)