JavaScript:使用Async/AWAIT和THEN/CATCH处理异步错误之间的差异
我只是想先发制人地说,我熟悉异步/等待和在JavaScript中的承诺,所以不需要为此将我链接到一些MDN页面。
我有一个获取用户详细信息并将其显示在UI上的函数。
async function someHttpCall() {
throw 'someHttpCall error'
}
async function fetchUserDetails() {
throw 'fetchUserDetails error'
}
function displayUserDetails(userDetails) {
console.log('userDetails:', userDetails)
}
async function fetchUser() {
try {
const user = await someHttpCall()
try {
const details = await fetchUserDetails(user)
returndisplayUserDetails(details)
} catch (fetchUserDetailsError) {
console.log('fetching user error', fetchUserDetailsError)
}
} catch (someHttpCallError) {
console.log('networking error:', someHttpCallError)
}
}
它首先通过someHttpCall
进行HTTP调用,如果成功,则转到fetchUserDetails
,如果也成功,则我们通过returndisplayUserDetails
显示有关UI的详细信息。
如果someHttpCall
失败,我们将停止并不进行fetchUserDetails
调用。换句话说,我们希望将someHttpCall
的错误处理和fetchUserDetails
的数据处理分开
我编写的函数包含嵌套的try catch
块,如果嵌套变得很深,则不能很好地伸缩,我正尝试使用普通then
和catch
重写它以提高可读性
这是我的第一次尝试
function fetchUser2() {
someHttpCall()
.then(
(user) => fetchUserDetails(user),
(someHttpCallError) => {
console.log('networking error:', someHttpCallError)
}
)
.then(
(details) => {
displayUserDetails(details)
}, //
(fetchUserDetailsError) => {
console.log('fetching user error', fetchUserDetailsError)
}
)
}
这样做的问题是,第二个then
将运行,即displayUserDetails
即使someHttpCall
失败。为了避免这种情况,我不得不让前面的.catch
块抛出
这就是更新版本
function fetchUser2() {
someHttpCall()
.then(
(user) => fetchUserDetails(user),
(someHttpCallError) => {
console.log('networking error:', someHttpCallError)
throw someHttpCallError
}
)
.then(
(details) => {
displayUserDetails(details)
}, //
(fetchUserDetailsError) => {
console.log('fetching user error', fetchUserDetailsError)
}
)
}
但是,现在第二个接球将作为抛出的结果被调用。因此,当someHttpCall
失败时,在我们处理了someHttpCallError
错误之后,我们将进入这个块(fetchUserDetailsError) => { console.log('fetching user error', fetchUserDetailsError) }
,这并不好,因为fetchUserDetails
从未被调用过,所以我们不需要处理fetchUserDetailsError
(我知道someHttpCallError
在这种情况下变成了fetchUserDetailsError
)
我可以在其中添加一些条件检查来区分这两个错误,但这似乎不太理想。因此,我想知道如何通过使用.then
和.catch
在这里实现相同的目标来改进这一点。
解决方案
我想知道如何通过使用
.then
和.catch
来改进这一点,以在这里实现相同的目标
如果您想要复制相同的行为,则无法避免嵌套:
function fetchUser2() {
return someHttpCall().then(
(user) => {
return fetchUserDetails(user).then(
(details) => {
return displayUserDetails(details)
},
(fetchUserDetailsError) => {
console.log('fetching user error', fetchUserDetailsError)
}
)
},
(someHttpCallError) => {
console.log('networking error:', someHttpCallError)
throw someHttpCallError
}
)
}
(完全等同于try
/catch
将使用.then(…).catch(…)
instead of .then(…, …)
,但you might not actually want that。)
我编写的函数是[嵌套的],如果嵌套变得很深,它就不能很好地伸缩,而我正试图重写它以提高可读性[…]
为此,我建议将await
与.catch()
结合使用:
async function fetchUser() {
try {
const user = await someHttpCall().catch(someHttpCallError => {
throw new Error('networking error', {cause: someHttpCallError});
});
const details = await fetchUserDetails(user).catch(fetchUserDetailsError => {
throw new Error('fetching user error', {cause: fetchUserDetailsError});
});
return displayUserDetails(details);
} catch (someError) {
console.log(someError.message, someError.cause);
}
}
(Error
的cause
选项仍然很新,您可能需要一个填充)
相关文章