【问题标题】:Escaping the promise chain when it's completed [duplicate]完成后逃离承诺链[重复]
【发布时间】:2018-10-22 10:02:48
【问题描述】:

我想在启动我的应用程序之前使用 Promise 链加载一些数据。所以,我会有类似的东西:

fetch('path/to/data.json')
  .then((response) => response.json())
  .then((data) => {
    console.log(`Hey cool, we're done w/ the promise chain here`);
    startApp(data);
  })
  .catch((error) => console.error(`Error in promise chain: ${error}`));

它确实有效——但使用此设置,我的 startApp 函数(或任何后续函数)中的任何错误都会在 Promise 链中得到处理,这似乎是错误的。

我发现的 Promise 示例通常以链的最后一个 then() 中的控制台日志结尾,因此它们对此没有太大的指导意义。

  • 我的设置方式真的好吗?
  • 如果没有,我怎么能等到承诺链的末尾才调用startApp 函数而不仍然在链中?

【问题讨论】:

  • 这很好....
  • .finally() 也是一个选项
  • 好的,好的,谢谢@DanielA.White
  • 如果你的startApp也是一个promise,请注意错误会丢失而不会被捕获。

标签: javascript promise


【解决方案1】:

您将永远处于承诺链中。但是,您可以轻松地将处理fetch 错误的逻辑与您的数据消耗应用程序分开,如下所示:

fetch('path/to/data.json')
  .then(response => response.json())
  .then(startApp, handleFetchError)
  .catch(error => console.error(`Error from startApp or handleFetchError: ${error}`));

【讨论】:

    【解决方案2】:

    根据问题中观察到的效果,Promise 实现在 try/catch 块内调用 .then 处理程序。如果捕获到错误,then 返回的 Promise 会以同样的原因被拒绝。

    要单独报告应用程序错误,您可以在应用程序周围放置自己的 try/catch 块并明确处理错误报告。如果顶级then 处理程序返回而没有重新抛出错误,则不会调用以下catch 处理程序。

    例如

    fetch('path/to/data.json')
      .then((response) => response.json())
      .then((data) => {
        console.log(`Hey cool, we're done w/ the promise chain here`);
        try {
              startApp(data);
        }
        catch( err) {
          console.log( "An application error occurred:");
          console.error( err);
        }
        // returning without re-throwing the error
      })
     .catch((error) => console.error(`Error in promise chain: ${error}`));
    

    我还看到用于在承诺链之外抛出错误的计时器调用,以防止它们被作为承诺错误消耗。不确定堆栈跟踪是否足够,但至少它可以确定发生了应用程序错误:

    例如

    fetch('path/to/data.json')
      .then((response) => response.json())
      .then((data) => {
        console.log(`Hey cool, we're done w/ the promise chain here`);
        try {
          startApp(data);
        }
        catch( err) {
            setTimeout( function () { throw err}, 0);
        }
    })
    .catch((error) => console.error(`Error in promise chain: ${error}`));
    

    另一种方法是使用计时器启动应用程序,这样它就不会在承诺链中执行以启动:-)

    setTimeout(startApp, 0, data);
    

    【讨论】:

    • 我对专门捕捉错误不太感兴趣,只是那种我认为应该在仍然存在于其中的承诺链之后出现的“错误”感觉。它有一种在大量代码周围放置 try/catch 的感觉。
    • setTimeout 实际上完成了这项工作,跳过了调用堆栈——但出于某种原因,感觉 more 错了哈哈
    • setTimeout 可以满足目的。注意 setTimout 不会“跳过调用堆栈”,因为承诺和计时器回调都使用新堆栈执行。最大的区别在于,promise 回调的执行由 then/catch 调用返回的 promise 的 executor 函数监控,以查看如果处理程序抛出错误,promise 是否应该被拒绝 - 而计时器回调只是报告未捕获的错误控制台作为“未捕获的异常”。
    猜你喜欢
    • 2018-07-21
    • 1970-01-01
    • 2021-05-12
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    相关资源
    最近更新 更多