JSON HTTP 请求的 Promise 中的 .catch 子句未捕获的错误
Uncaught errors by .catch clause in Promise for JSON HTTP request
我有这个功能可以从 API 端点收集 JSON 数据:
export const getDataAPI = (token_id) => {
const url = `https://api.url.com/tokens/` + token_id;
const options = {method: 'GET', headers: {Accept: 'application/json'}};
const request = fetch(url, options)
.then(response => { if (response.status === 200) {
return response.json();
} else if ([404, 429, 500].includes(response.status)) {
return response.status;
} else {
return response.json()
.then(json => {
console.log("Error: getDataAPI response status", response.status);
throw json;
})
}
})
.catch(error => { throw error; });
return Promise.resolve(request);
};
我用这个功能收集了超过130万条记录。我想捕捉任何意想不到的问题,这样我就可以优雅地暂停几秒钟,然后重试。但是我遇到了 2 个未发送到 .catch 子句的错误。即使 response
为空/空/未定义,我也希望至少能看到 console.log("Error: getDataAPI response status", response.status);
的输出
这些错误每个只发生一次。
undefined:1
SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at Response.json (file:///home/user/node_modules/node-fetch/src/body.js:149:15)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async file:///home/user/path/to/file.mjs:94:20
file:///home/user/node_modules/node-fetch/src/index.js:108
reject(new FetchError(`request to ${request.url} failed, reason: ${error.message}`, 'system', error));
^
FetchError: request to https://api.url.com/tokens/29727608 failed, reason: read ECONNRESET
at ClientRequest.<anonymous> (file:///home/user/node_modules/node-fetch/src/index.js:108:11)
at ClientRequest.emit (node:events:526:28)
at TLSSocket.socketErrorListener (node:_http_client:442:9)
at TLSSocket.emit (node:events:526:28)
at emitErrorNT (node:internal/streams/destroy:157:8)
at emitErrorCloseNT (node:internal/streams/destroy:122:3)
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
type: 'system',
errno: 'ECONNRESET',
code: 'ECONNRESET',
erroredSysCall: 'read'
}
我不明白为什么这些错误没有被函数捕获。有人可以解释一下吗?
我怎样才能修复这个函数,让它也能捕捉到这类错误?
我应该寻找什么输出来识别这些错误,SyntaxError
和 FetchError
?例如,是否有用于监视错误代码的变量?
I would expect at least to see the output of console.log("Error: getDataAPI response status", response.status);
该代码不在 catch 子句中,它在 then
子句中。
return response.json()
.then(json => {
console.log("Error: getDataAPI response status", response.status);
throw json;
})
您的 catch
只是重新抛出:
.catch(error => { throw error; });
这会给你一个未捕获的错误。
您需要 log/handle 捕获错误,而不是 then
子句:
export const getDataAPI = (token_id) => {
const url = `https://api.url.com/tokens/` + token_id;
const options = {method: 'GET', headers: {Accept: 'application/json'}};
const request = fetch(url, options)
.then(response => { if (response.status === 200) {
return response.json();
} else if ([404, 429, 500].includes(response.status)) {
return response.status;
} else {
console.log("Error: getDataAPI response status", response.status);
// you can swallow the error here if you want, or try to parse it anyway
return response.json()
}
})
.catch(error => {
console.log('Handling error', error);
throw error;
});
// wrapping the request in a Promise.resolve is also unnecessary
// return Promise.resolve(request);
return request;
};
在 xdumaine 的帮助下,我能够弄清楚我做错了什么。
这些错误没有触发 console.log
报告,因为它们甚至在可以组成 JSON 字符串之前就已经出现了。
函数正在捕获错误,只是没有对它们做任何事情。我发现 this page 有助于更好地理解和测试它。作为演示,这是一种创建错误并确认 .catch() 子句正在处理它的方法:
export const getDataAPI = (token_id) => {
const url = `https://api.url.com/tokens/` + token_id;
const options = {method: 'GET', headers: {Accept: 'application/json'}};
const request = fetch(url, options)
.then(response => {
throw new SyntaxError('Hello', 'someFile.js', 10);
if (response.status === 200) {
return response.json();
} else if ([404, 429, 500].includes(response.status)) {
return response.status;
} else {
return response.json()
.then(json => {
console.log("Error: getDataAPI response status", response.status);
throw json;
})
}
})
.catch(error => {
console.log('Caught error', error.name);
throw error;
});
return request;
};
- 如上面链接的页面所示,
error.name
包含错误的名称。
我有这个功能可以从 API 端点收集 JSON 数据:
export const getDataAPI = (token_id) => {
const url = `https://api.url.com/tokens/` + token_id;
const options = {method: 'GET', headers: {Accept: 'application/json'}};
const request = fetch(url, options)
.then(response => { if (response.status === 200) {
return response.json();
} else if ([404, 429, 500].includes(response.status)) {
return response.status;
} else {
return response.json()
.then(json => {
console.log("Error: getDataAPI response status", response.status);
throw json;
})
}
})
.catch(error => { throw error; });
return Promise.resolve(request);
};
我用这个功能收集了超过130万条记录。我想捕捉任何意想不到的问题,这样我就可以优雅地暂停几秒钟,然后重试。但是我遇到了 2 个未发送到 .catch 子句的错误。即使 response
为空/空/未定义,我也希望至少能看到 console.log("Error: getDataAPI response status", response.status);
的输出
这些错误每个只发生一次。
undefined:1
SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at Response.json (file:///home/user/node_modules/node-fetch/src/body.js:149:15)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async file:///home/user/path/to/file.mjs:94:20
file:///home/user/node_modules/node-fetch/src/index.js:108
reject(new FetchError(`request to ${request.url} failed, reason: ${error.message}`, 'system', error));
^
FetchError: request to https://api.url.com/tokens/29727608 failed, reason: read ECONNRESET
at ClientRequest.<anonymous> (file:///home/user/node_modules/node-fetch/src/index.js:108:11)
at ClientRequest.emit (node:events:526:28)
at TLSSocket.socketErrorListener (node:_http_client:442:9)
at TLSSocket.emit (node:events:526:28)
at emitErrorNT (node:internal/streams/destroy:157:8)
at emitErrorCloseNT (node:internal/streams/destroy:122:3)
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
type: 'system',
errno: 'ECONNRESET',
code: 'ECONNRESET',
erroredSysCall: 'read'
}
我不明白为什么这些错误没有被函数捕获。有人可以解释一下吗?
我怎样才能修复这个函数,让它也能捕捉到这类错误?
我应该寻找什么输出来识别这些错误,
SyntaxError
和FetchError
?例如,是否有用于监视错误代码的变量?
I would expect at least to see the output of console.log("Error: getDataAPI response status", response.status);
该代码不在 catch 子句中,它在 then
子句中。
return response.json()
.then(json => {
console.log("Error: getDataAPI response status", response.status);
throw json;
})
您的 catch
只是重新抛出:
.catch(error => { throw error; });
这会给你一个未捕获的错误。
您需要 log/handle 捕获错误,而不是 then
子句:
export const getDataAPI = (token_id) => {
const url = `https://api.url.com/tokens/` + token_id;
const options = {method: 'GET', headers: {Accept: 'application/json'}};
const request = fetch(url, options)
.then(response => { if (response.status === 200) {
return response.json();
} else if ([404, 429, 500].includes(response.status)) {
return response.status;
} else {
console.log("Error: getDataAPI response status", response.status);
// you can swallow the error here if you want, or try to parse it anyway
return response.json()
}
})
.catch(error => {
console.log('Handling error', error);
throw error;
});
// wrapping the request in a Promise.resolve is also unnecessary
// return Promise.resolve(request);
return request;
};
在 xdumaine 的帮助下,我能够弄清楚我做错了什么。
这些错误没有触发
console.log
报告,因为它们甚至在可以组成 JSON 字符串之前就已经出现了。函数正在捕获错误,只是没有对它们做任何事情。我发现 this page 有助于更好地理解和测试它。作为演示,这是一种创建错误并确认 .catch() 子句正在处理它的方法:
export const getDataAPI = (token_id) => {
const url = `https://api.url.com/tokens/` + token_id;
const options = {method: 'GET', headers: {Accept: 'application/json'}};
const request = fetch(url, options)
.then(response => {
throw new SyntaxError('Hello', 'someFile.js', 10);
if (response.status === 200) {
return response.json();
} else if ([404, 429, 500].includes(response.status)) {
return response.status;
} else {
return response.json()
.then(json => {
console.log("Error: getDataAPI response status", response.status);
throw json;
})
}
})
.catch(error => {
console.log('Caught error', error.name);
throw error;
});
return request;
};
- 如上面链接的页面所示,
error.name
包含错误的名称。