完成后逃离承诺链[重复]

Posted

技术标签:

【中文标题】完成后逃离承诺链[重复]【英文标题】: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,请注意错误会丢失而不会被捕获。 【参考方案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 是否应该被拒绝 - 而计时器回调只是报告未捕获的错误控制台作为“未捕获的异常”。

以上是关于完成后逃离承诺链[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Jquery 承诺链

Javascript,如何等待多个承诺[重复]

jQuery Deferred - 等待多个 AJAX 请求完成 [重复]

如何等到承诺完成后再继续循环

连接完成后承诺不解决

Javascript承诺链与重复逻辑附加到同一项目数组中。