不使用 try-catch 在 async-await 中捕获错误和数据
席卷 JavaScript 社区的一件事就是 async-await 的推出。它简洁易用,比 Promises 的 then-catch 代码看起来好很多,也比回调地狱更易读、更易于调试。但 try-catch 的使用却让我很困扰。起初我以为这没什么问题,但命运弄人,我在处理链式 API 调用时,问题出现了:每个 API 调用都需要打印特定的错误消息。我很快意识到,我正在创造一个 try-catch 地狱。
让我们考虑一下这个 Promise,它根据参数在 2 秒后解析或拒绝rejectPromise
// api.js
const fetchData = async (duration, rejectPromise) => (
new Promise((resolve, reject) => {
setTimeout(() => {
if (rejectPromise) {
reject({
error: 'Error Encountered',
status: 'error'
})
}
resolve({
version: 1,
hello: 'world',
});
}, duration);
})
);
module.exports = {
fetchData,
};
所以我对 async-await 的典型用法是这样的。
const { fetchData } = require('./api');
const callApi = async () => {
try {
const value = await fetchData(2000, false);
console.info(value);
} catch (error) {
console.error(error);
}
}
callApi();
/*
OUTPUT:
{ version: 1, hello: 'world' } (rejectPromise=false)
{ error: 'Error Encountered', status: 'error' } (rejectPromise=true)
*/
正如您所看到的,当rejectPromise
参数为时, false
await 解析为,{ version: 1, hello: 'world' }
而当参数为时,true
它拒绝承诺并调用 catch,错误为{ error: 'Error Encountered', status: 'error' }
。
这就是 async-await 的典型实现。现在,我们将利用 promise 函数 then-catch 来简化这个过程。让我们编写一个包装器来实现这一点。
// wrapper.js
const wrapper = promise => (
promise
.then(data => ({ data, error: null }))
.catch(error => ({ error, data: null }))
);
module.exports = wrapper;
我们可以看到,包装器接受一个 Promise 作为输入,并通过 then-catch 返回已解析/已拒绝的值。那么,让我们修改一下我们之前在 try-catch 中编写的代码,以便使用这个包装器。
const { fetchData } = require('./api');
const wrapper = require('./wrapper');
const callApi = async () => {
const { error, data } = await wrapper(fetchData(2000, false));
if (!error) {
console.info(data);
return;
}
console.error(error);
}
callApi();
/*
OUTPUT:
{ version: 1, hello: 'world' } (rejectPromise=false)
{ error: 'Error Encountered', status: 'error' } (rejectPromise=true)
*/
瞧,输出相同,但这种方式更容易理解代码。
文章来源:https://dev.to/sadarshannaiynar/capture-error-and-data-in-async-await-without-try-catch-1no2