当 createAsyncThunk 调度的 Promise 被拒绝时如何访问错误对象?
How to access the error object when the Promise of a createAsyncThunk dispatch is rejected?
我想分别处理承诺被履行和被拒绝的情况。我看到在我的代码中,传递给 then 的第一个函数总是被调用,即使在 promise 被拒绝时也是如此。
我有这样的代码,在评论中解释了问题:
dispatch(reduxActionCreatorHere(/* ...)*/).then((d) => {
if (d.error) { // TS error: `error` missing from `d`, although the promise is rejected and the `error` field is accessible in pure JS (tested in Chromium DevTools)
// ...
}
// ...
}
像这样:
export const resetPassword = createAsyncThunk(
"auth/resetPassword",
async (options: { email: string }, thunkAPI) => {
debugger;
return await new Promise<void>((resolve, reject) => {
setTimeout(() => {
requestPasswordCrud(options.email).then(
() => {
console.log("password reset");
resolve();
},
() => {
reject();
}
);
}, 1000);
});
}
);
更新 1
实际的错误信息是:
Property 'error' does not exist on type 'PayloadAction<void, string, { arg: { email: string; }; requestId: string; }, never> | PayloadAction<unknown, string, { arg: { email: string; }; requestId: string; aborted: boolean; condition: boolean; }, SerializedError>'.
Property 'error' does not exist on type 'PayloadAction<void, string, { arg: { email: string; }; requestId: string; }, never>'. TS2339
TL;DR 您需要使用 unwrapResult
来捕获由 createAsyncThunk
. 创建的异步 thunk 错误
如 docs 所述,使用 createAsyncThunk
创建的已调度 thunk 将始终 return 已解决的承诺。
如果你想处理失败的场景,你需要 unwrap
承诺。然而,我会在消费者中处理这个问题。
// action
export const resetPassword = createAsyncThunk("auth/resetPassword", requestPasswordCrud);
// consumer
import { unwrapResult } from '@reduxjs/toolkit';
const dispatch = useDispatch(); // if you are using react-redux
useEffect(() => {
dispatch(resetPassword())
.then(unwrapResult)
.then(actualResponse => {})
.catch(actualError => {})
}, [])
或者您可以创建一个未包装的调度助手:
import { unwrapResult } from '@reduxjs/toolkit';
const unwrapDispatch = dispatch => thunk => dispatch(thunk).then(unwrapResult);
//consume
const unwrappedDispatch = unwrapDispatch(dispatch);
unwrappedDispatch(resetPassword);
编辑:现在在@reduxjs/toolkit@1.6.0 中,使用createAsyncThunk
创建的承诺包含一个.unwrap()
方法来自动解包结果。
我想分别处理承诺被履行和被拒绝的情况。我看到在我的代码中,传递给 then 的第一个函数总是被调用,即使在 promise 被拒绝时也是如此。
我有这样的代码,在评论中解释了问题:
dispatch(reduxActionCreatorHere(/* ...)*/).then((d) => {
if (d.error) { // TS error: `error` missing from `d`, although the promise is rejected and the `error` field is accessible in pure JS (tested in Chromium DevTools)
// ...
}
// ...
}
像这样:
export const resetPassword = createAsyncThunk(
"auth/resetPassword",
async (options: { email: string }, thunkAPI) => {
debugger;
return await new Promise<void>((resolve, reject) => {
setTimeout(() => {
requestPasswordCrud(options.email).then(
() => {
console.log("password reset");
resolve();
},
() => {
reject();
}
);
}, 1000);
});
}
);
更新 1
实际的错误信息是:
Property 'error' does not exist on type 'PayloadAction<void, string, { arg: { email: string; }; requestId: string; }, never> | PayloadAction<unknown, string, { arg: { email: string; }; requestId: string; aborted: boolean; condition: boolean; }, SerializedError>'.
Property 'error' does not exist on type 'PayloadAction<void, string, { arg: { email: string; }; requestId: string; }, never>'. TS2339
TL;DR 您需要使用 unwrapResult
来捕获由 createAsyncThunk
. 创建的异步 thunk 错误
如 docs 所述,使用 createAsyncThunk
创建的已调度 thunk 将始终 return 已解决的承诺。
如果你想处理失败的场景,你需要 unwrap
承诺。然而,我会在消费者中处理这个问题。
// action
export const resetPassword = createAsyncThunk("auth/resetPassword", requestPasswordCrud);
// consumer
import { unwrapResult } from '@reduxjs/toolkit';
const dispatch = useDispatch(); // if you are using react-redux
useEffect(() => {
dispatch(resetPassword())
.then(unwrapResult)
.then(actualResponse => {})
.catch(actualError => {})
}, [])
或者您可以创建一个未包装的调度助手:
import { unwrapResult } from '@reduxjs/toolkit';
const unwrapDispatch = dispatch => thunk => dispatch(thunk).then(unwrapResult);
//consume
const unwrappedDispatch = unwrapDispatch(dispatch);
unwrappedDispatch(resetPassword);
编辑:现在在@reduxjs/toolkit@1.6.0 中,使用createAsyncThunk
创建的承诺包含一个.unwrap()
方法来自动解包结果。