Чистый способ действия для запуска нескольких асинхронных действий с createAsyncThunk

Мы откладываем рендеринг нашего веб-приложения React-Redux до тех пор, пока не будут завершены несколько задач инициализации асинхронного приложения в магазине 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))
            })
        )
)

Этот код прекрасно работает. Если какое-либо из этих действий не удается, обещание отклоняется, и пользователь видит сообщение об ошибке. Но это уродливо - это не так красиво, как у наших обычных создателей экшенов:

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

В какой-то момент мы будем запускать более одного запроса на выборку в fetchAppInitialization, Итак Promise.allфункция обязательно требуется. Мы хотели бы иметь возможность использовать Redux-ToolkitcreateAction синтаксис для запуска нескольких обещанных действий, чтобы сократить этот создатель действия, но я понятия не имею, возможно ли это вообще.

Примечание: я использую redux-requests для обработки моих запросов axios.

Является createAsyncThunk даже требуется?

1 ответ

Поскольку я не использовал 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
}
Другие вопросы по тегам