当 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() 方法来自动解包结果。