You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

无法捕获Promise抛出的异常:fetch请求JSON解析异常处理求助

嘿,我找到问题所在了!你的代码失效的核心原因出在catch块里的Map初始化逻辑,咱们一步步拆解来看:

问题根源

当你创建这个错误处理Map的时候:

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);

这里的JSON.parse(exception.message)立即执行的——也就是说,不管当前捕获的异常是什么类型,代码都会先尝试把exception.message解析成JSON。

举个例子,当服务器返回HTML内容时,response.json()抛出SyntaxError,此时exception.message是类似"Unexpected token < in JSON at position 0"的字符串,完全不是合法的JSON格式。这时候JSON.parse会直接抛出新的异常,导致你的catch块本身崩溃,自然无法正确返回预期的错误对象。

修复方案

你需要把每个错误类型对应的处理逻辑改成延迟执行的函数,只有当匹配到对应的异常类型时,才执行对应的解析或返回操作。修改后的catch块如下:

.catch(exception => {
  // 用函数包裹处理逻辑,延迟执行
  const errorHandlerMap = new Map([
    [TypeError, () => ["There was a problem fetching the response."]],
    [SyntaxError, () => ["There was a problem parsing the response."]],
    [Error, () => JSON.parse(exception.message)]
  ]);
  
  // 获取当前异常对应的处理函数,执行得到错误内容
  const errorHandler = errorHandlerMap.get(exception.constructor);
  const error = errorHandler ? errorHandler() : ["Unknown error occurred."];
  
  return { error };
})

这样改动后:

  • 只有当捕获到Error类型的异常时(也就是你在第二个then里主动抛出的情况),才会执行JSON.parse(exception.message),而此时exception.message是你之前用JSON.stringify(json)生成的合法JSON字符串,不会出错。
  • 捕获到SyntaxErrorTypeError时,直接返回对应的错误提示,不会触发多余的解析操作。

额外优化建议

其实你还可以在尝试解析JSON之前,先检查响应的Content-Type头,提前判断是否是JSON格式,避免不必要的解析错误:

fetch('/example.json')
  .then(response => {
    // 先检查响应的Content-Type是否为JSON类型
    const contentType = response.headers.get('content-type');
    if (!contentType || !contentType.includes('application/json')) {
      throw new SyntaxError('Response content is not JSON');
    }
    return Promise.all([response, response.json()]);
  })
  .then(([response, json]) => {
    if (!response.ok) {
      throw new Error(JSON.stringify(json));
    }
    return json;
  })
  .catch(exception => {
    const errorHandlerMap = new Map([
      [TypeError, () => ["There was a problem fetching the response."]],
      [SyntaxError, () => ["There was a problem parsing the response."]],
      [Error, () => JSON.parse(exception.message)]
    ]);
    
    const errorHandler = errorHandlerMap.get(exception.constructor);
    const error = errorHandler ? errorHandler() : ["Unknown error occurred."];
    
    return { error };
  })

这样可以在解析前就拦截非JSON响应,让错误处理逻辑更前置、更清晰。

内容的提问来源于stack exchange,提问作者jorbuedo

火山引擎 最新活动