【问题标题】:Cancel next promise if previous failed (synchronously)如果上一个失败(同步)取消下一个承诺
【发布时间】:2020-08-01 20:05:39
【问题描述】:

我有一个案例,如果之前的操作成功,我会发送电子邮件。

Promise.all([doSomeAction(), sendMailIfSuccess()]) // both of them are promises
   .then(() => success)
   .catch(() => err);

但是,如果 doSomeAction() 承诺在 sendMailIfSuccess 解析之前失败,则无论如何都会发送邮件。但它不应该。

问题:如何仅在doSomeAction 解决后才调用sendMailIfSuccess 承诺? sendMailIfSuccess 承诺应该等待 doSomeAction 承诺。

【问题讨论】:

    标签: javascript asynchronous ecmascript-6 promise async-await


    【解决方案1】:

    由于您想连续运行这两个进程,并且只有在第一个进程成功时才运行第二个进程,所以 Promise.all 在这里不是正确的工具 - 只需改用 .then

    doSomeAction()
      .then(() => sendMailIfSuccess())
      .catch( /* handle errors, including doSomeAction failures */);
    

    【讨论】:

    • 谢谢。如果sendMailIfSuccess 成功,我想做一些事情怎么办?我可以把第二个then放在哪里?
    • .then之后:.then(() => sendMailIfSuccess()).then(() => console.log('mail sent'))
    • 不应该是=> sendMailIfSuccess().then(() => 'mail sent')吗?有什么区别?
    • 这会导致嵌套 .thens,这是 Promise 的反模式 - 拥有 flat .then 链的能力是 Promise 相对于回调的最大优势之一.如果您利用它,代码将更易于阅读。如果你愿意,你可以,但我不推荐。
    【解决方案2】:

    你也可以使用async/await

    async function f(){
      let result1 = await doSomeAction()
      let result2 = await sendMailIfSuccess()
    }
    
    try {
     f()
    } catch(err) {
     //handle error
    }
    

    【讨论】:

      【解决方案3】:

      正如@CertainPerformance 所述,如果您希望这些方法串联运行。您应该在从第一个方法获得成功响应后调用第二个方法。

      doSomeAction()
        .then(res => {
          /* do something with the res, if needed */
          return sendMailIfSuccess();
        })
        .catch(err => {
          /* handle errors */
        });
      

      为什么Promise.all(...) 不是正确的选择? 如前所述here

      它通常在启动多个异步任务并发运行并为其结果创建承诺后使用,以便可以等待所有任务完成。

      同理,还有Promise.race(...)here,当我们需要iterable中第一个resolved或者rejected时使用。

      【讨论】:

      • 返回 sendMailIfSuccess();
      猜你喜欢
      • 2019-08-21
      • 2017-11-03
      • 1970-01-01
      • 2013-09-29
      • 2019-08-20
      • 2021-02-18
      • 2017-05-16
      • 1970-01-01
      • 2023-03-18
      相关资源
      最近更新 更多