首页 > 解决方案 > 一种使用 createAsyncThunk 触发多个异步操作的简洁方法

问题描述

我们正在延迟 React-Redux Web 应用程序的渲染,直到 Redux 商店中的几个异步应用程序初始化任务完成。

这是设置存储然后触发初始化操作的代码:

export const setupStoreAsync = () => {
    return new Promise((resolve, reject) => {
        const store = setupStore()
        store
            .dispatch(fetchAppInitialization())
            .then(unwrapResult)
            .then(_ => resolve(store))
            .catch(e => reject(e.message))
    })
}

承诺拒绝非常重要,因为它用于在应用程序无法正确设置的情况下为用户呈现错误消息。这段代码非常好读并且运行良好。

问题在于动作创建者:

export const fetchAppInitialization = createAsyncThunk(
    'app/initialization',
    (_, thunkApi) =>
        new Promise((resolve, reject) =>
            Promise.all([thunkApi.dispatch(fetchVersionInfo())]).then(results => {
                results.map(result => result.action.error && reject(result.error))
            })
        )
)

这段代码工作得很好。如果这些操作中的任何一个失败,则 Promise 将被拒绝,并且用户会看到一条错误消息。但它很丑 - 它不像我们正常的动作创作者那么漂亮:

export const fetchVersionInfo = createAction('system/versionInfo', _ => ({
    payload: {
        request: { url: `/system/versionInfo` },
    },
}))

我们会在某个时候触发多个 fetch 请求fetchAppInitialization,所以这个Promise.all函数肯定是必需的。我们希望能够使用 Redux-Toolkit 的createAction语法来触发多个承诺的动作,以缩短这个动作创建者,但我不知道这是否可能。

注意:我redux-requests用来处理我的 axios 请求。

甚至是createAsyncThunk必需的吗?

标签: reduxpromisees6-promiseredux-thunkredux-toolkit

解决方案


因为fetchAppInitialization除了这个单一的用例我没有使用任何动作,我只是简单地删除它并将逻辑直接移动到setupStoreAsync函数中。这有点紧凑。这不是最优的,因为results.map仍然包含逻辑,但至少我们不再使用createAsyncThunk

export const setupStoreAsync = () => {
    return new Promise((resolve, reject) => {
        const store = setupStore()

        new Promise((resolve, reject) =>
            Promise.all([store.dispatch(fetchVersionInfo())]).then(results => {
                results.map(result => result.action.error && reject(result.error))
                resolve()
            })
        )
            .then(_ => resolve(store))
            .catch(e => reject(e.message))
    })
}

更新:我能够通过使用async/await.

export const setupStoreAsync = async () => {
    const store = setupStore()

    const results = await Promise.all([store.dispatch(fetchVersionInfo())])
    results.forEach(result => {
        if (result.action.error) throw result.error
    })
    return store
}

推荐阅读