使用 createAsyncThunk 触发多个异步操作的简洁方法
A clean way for an action to fire multiple asynchronous actions with 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-Toolkit 的 createAction
语法来触发多个 promisified 动作以缩短这个动作创建者,但我不知道这是否可能。
注意:我正在使用 redux-requests
来处理我的 axios 请求。
还需要createAsyncThunk
吗?
由于除了这个单一用例之外,我没有将 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
}
我们正在延迟 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-Toolkit 的 createAction
语法来触发多个 promisified 动作以缩短这个动作创建者,但我不知道这是否可能。
注意:我正在使用 redux-requests
来处理我的 axios 请求。
还需要createAsyncThunk
吗?
由于除了这个单一用例之外,我没有将 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
}