Чистый способ действия для запуска нескольких асинхронных действий с 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
}