当前位置: 首页 > 面试题库 >

断开promise链,并根据该链中被破坏(被拒绝)的步骤调用函数

公西国发
2023-03-14
问题内容

更新:

为了帮助以后的读者,我创建 了pluma’s answer的演示 。

题:

我的目标似乎很简单。

  step(1)
  .then(function() {
    return step(2);
  }, function() {
    stepError(1);
    return $q.reject();
  })
  .then(function() {

  }, function() {
    stepError(2);
  });

  function step(n) {
    var deferred = $q.defer();
    //fail on step 1
    (n === 1) ? deferred.reject() : deferred.resolve();
    return deferred.promise;
  }
  function stepError(n) {
    console.log(n); 
  }

这里的问题是,如果我在步骤1上失败,则两个stepError(1)AND都会stepError(2)被触发。如果我不return $q.reject那么stepError(2)就不会被解雇,但step(2)会,我明白了。除了我想做的以外,我已经完成了所有工作。

如何编写promise,以便我可以在拒绝时调用函数,而无需调用错误链中的所有函数?还是有另一种方法可以做到这一点?

这是一个现场演示, 因此您可以进行一些工作。

更新:

有点
解决了。在这里,我在链的末尾捕获错误,并将数据传递给reject(data)我,以便我知道在错误函数中要处理的问题。这实际上不符合我的要求,因为我不想依赖数据。这很la脚,但在我的情况下,将错误回调传递给函数而不是依靠返回的数据来确定要做什么,会更干净。

现场演示在这里(单击)。

step(1)
  .then(function() {
    return step(2);
  })
  .then(function() {
    return step(3);
  })
  .then(false, 
    function(x) {
      stepError(x);
    }
  );
  function step(n) {
    console.log('Step '+n);
    var deferred = $q.defer();
    (n === 1) ? deferred.reject(n) : deferred.resolve(n);
    return deferred.promise;
  }
  function stepError(n) {
    console.log('Error '+n); 
  }

问题答案:

您的代码无法按预期运行的原因是,它实际上在做一些与您认为的有所不同的事情。

假设您有类似以下内容的东西:

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仅当该步骤被拒绝(但主链无法直接到达)时才调用该子链。

这样做的原因是onFulfilledonRejected都是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



 类似资料:
  • Re:https://github.com/tildeio/rsvp.js 我有一个函数,名为do某物(),它做了一会儿事情,然后返回一个RSVP. Promise。然后,一个成功和失败的回调链被注册为返回的promise(见下面的代码)。我所期望的行为是,如果promise兑现,用promise注册的成功回调链将被解雇,如果promise被拒绝(失败),失败回调链将被解雇。 当promise兑现

  • 我一直在使用异步生成器,试图创建一个“promise排序”生成器,它接受一系列promise,并按照promise解析或拒绝的顺序逐个生成promise。比如: 有了这样消耗这个发电机的想法: 然而,我注意到,这将达到第二个promise,然后发电机将停止。这似乎是因为拒绝了“第二次”promise。当被拒绝时,在生成器中调用将在生成器中创建异常。 但这是我困惑的根源。我不想在这里创建异常,我只想

  • 问题内容: 我无法使用带有command的react.js启动我的项目。得到错误: npm 5.0.3。节点8.1.4。纱线0.24.5 macOS Sierra 10.12.4 当我再次启动命令时,它将安装软件包,但是在命令后,它将显示以下内容: 我试图通过添加Sharp ,但收到相同的错误。EACCES:权限被拒绝 问题答案: 首先,您需要通过运行以下命令来检查权限: 我收到了下一个答复: 比

  • 问题内容: 我有两个文件:b.php和test.txt 错误是:警告:unlink(test.txt)[function.unlink]:权限被拒绝 为什么?b.php和test.txt是777,并且相同的组/登录名 如果我在父目录上设置了777,则可以执行取消链接,但必须将777设置回755? 问题答案: 您(在运行过程中,无论您是通过网络服务器还是通过网络服务器)都需要对文件所在目录的写权限。

  • 问题内容: 我目前正在尝试诺言,并且有一个非常基本的问题! 在一个Promise链中,调用同步函数是否是错误的做法?例如: 还是应该将我的同步功能重构为也返回承诺? 问题答案: 在一个Promise链中,调用同步函数是否是错误的做法? 不,这根本不是一个坏习惯。这是许多预期和有用的实践之一。 您可以完全自由地(在处理程序中)调用promise链中的同步函数或异步函数,然后再返回新的promise。

  • 我试图让我的头周围的promise,我得到了这个错误抱怨未处理的promise拒绝,但我确实有一个<代码>捕捉如果它被拒绝! 谁能帮帮我我做错了什么? 这是我的代码: 错误: (节点:200092)未处理的PromisejectionWarning:未处理的promise拒绝。这个错误要么是由于在没有catch块的情况下抛出异步函数的内部,要么是因为拒绝了没有使用catch块处理的promise。