一种使用createAsyncThunk触发多个异步操作的操作的干净方法

时间:2020-08-26 10:06:53

标签: redux promise es6-promise redux-thunk redux-toolkit

我们将延迟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))
    })
}

Promise拒绝非常重要,因为它用于在无法正确设置应用程序的情况下为用户呈现错误消息。这段代码非常好阅读,效果很好。

问题出在动作创建者上:

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))
            })
        )
)

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

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

我们有时会在fetchAppInitialization中触发多个获取请求,因此肯定需要Promise.all函数。我们希望能够使用Redux-Toolkit的createAction语法来触发多个已承诺的操作,以缩短该操作的创建者,但是我不知道这是否可能。

注意:我正在使用redux-requests处理我的axios请求。

甚至需要createAsyncThunk吗?

1 个答案:

答案 0 :(得分:0)

由于除了这个单一用例之外,我没有使用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
}