#redux #promise #es6-promise #redux-thunk #redux-toolkit
#сокращение #обещание #es6-обещание #сокращение-thunk #сокращение-инструментарий
Вопрос:
Мы откладываем рендеринг нашего веб-приложения React-Redux до тех пор, пока не будут выполнены несколько задач инициализации асинхронного приложения в Redux Store.
Вот код, который настраивает хранилище, а затем запускает действие инициализации:
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 amp;amp; reject(result.error))
})
)
)
Этот код работает прекрасно. Если какое-либо из этих действий завершается неудачей, обещание отклоняется, и пользователь видит сообщение об ошибке. Но это некрасиво — это не так красиво, как наши обычные создатели действий:
export const fetchVersionInfo = createAction('system/versionInfo', _ => ({
payload: {
request: { url: `/system/versionInfo` },
},
}))
В какой-то момент мы запустим более одного запроса на выборку fetchAppInitialization
, поэтому Promise.all
функция определенно требуется. Мы хотели бы иметь возможность использовать createAction
синтаксис Redux-Toolkit для запуска нескольких обещанных действий, чтобы сократить этот action creator, но я понятия не имею, возможно ли это вообще.
Примечание: Я использую redux-requests
для обработки своих запросов axios.
createAsyncThunk
Даже требуется?
Комментарии:
1. Используете ли вы вообще результирующие действия жизненного цикла? Если нет, то да, вы немного переусердствовали и могли бы просто переместить это в свой setupStoreAsync с помощью
.catch
😉
Ответ №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 amp;amp; 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
}
Комментарии:
1. Обратите внимание, что вы, вероятно, могли бы сократить эту логику, используя
async/await
вместоnew Promise
.