【问题标题】:Can't catch exception from promise无法从承诺中捕获异常
【发布时间】:2019-01-30 23:58:09
【问题描述】:

这段代码有问题:

fetch('/example.json')
  .then(response => Promise.all([response, response.json()])) // This line throws unhandled exception: SyntaxError: Unexpected token < in JSON at position 0
  .then(([response, json]) => {
    if (!response.ok) {
      throw new Error(JSON.stringify(json));
    }
    return json;
  })
  .catch(exception => {
    const error = new Map([
      [TypeError, ["There was a problem fetching the response."]],
      [SyntaxError, ["There was a problem parsing the response."]],
      [Error, JSON.parse(exception.message)]
    ]).get(exception.constructor);

    return { error };
  })

它在大多数情况下都可以正常工作,但是当服务器的响应为 200 OK 时它会失败,但实际内容是 HTML。我知道这是服务器上的错误,但我只想让我的客户正确处理它。也就是说,它应该使用最终的 catch 来捕获 response.json() 异常。

我做错了什么?

【问题讨论】:

  • 调用JSON.parse(exception.message) 而不考虑实际的exception 看起来是个坏主意。
  • 究竟是什么让您认为您的最终catch 没有处理异常?
  • 进一步观察,catch 也确实执行了。但是,打开 devtools 的 Chrome 会在 response.json() 上停止执行(恢复执行后,它会执行 catch)。在捕获发生之前停止执行是正常的 devtools 行为吗?
  • 我认为是的,它停在引发异常/拒绝承诺的行上,而不仅仅是在您可能设置断点的 catch 上。
  • 这段代码太奇怪了,以至于它会很麻烦。 Promise.all() 在那个位置是不合适的,很可能是这里所有问题的原因。 Promise.all() 的第一个参数是从请求中解析的 Promise,因此什么都不做,第二个是通常预期的操作,它解析(在这种情况下)解析为 JSON。 if(!response.ok) 条件代码应放在第一个 .then() 内,因为这是处理响应的适当时间。那么“良好”条件下的返回语句应该是return response.json()

标签: javascript promise fetch


【解决方案1】:

感谢Bergi的评论发现了问题。

不管你得到的实际异常是什么,都调用 JSON.parse(exception.message) 看起来是个坏主意。

catch 上的那一行导致了 catch 内部的第二个异常,从而导致了所有的麻烦。

关于即使未选中“捕获异常时暂停”,开发工具也会停止,看起来这不适用于 Promise 捕获:https://bugs.chromium.org/p/chromium/issues/detail?id=465666

【讨论】:

    猜你喜欢
    • 2020-12-17
    • 2018-07-24
    • 1970-01-01
    • 2018-03-16
    • 2016-10-05
    • 2014-06-13
    • 2018-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多