无法捕获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字符串,不会出错。 - 捕获到
SyntaxError或TypeError时,直接返回对应的错误提示,不会触发多余的解析操作。
额外优化建议
其实你还可以在尝试解析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




