gpt4 book ai didi

javascript - 如何从 redux-observable 调度多个 Action ?

转载 作者:搜寻专家 更新时间:2023-11-01 04:56:06 26 4
gpt4 key购买 nike

我想从 redux-observable 史诗中分派(dispatch)多个 Action 。我该怎么做?我最初是从

const addCategoryEpic = action$ => {
return action$.ofType(ADD_CATEGORY_REQUEST)
.switchMap((action) => {
const db = firebase.firestore()
const user = firebase.auth().currentUser
return db.collection('categories')
.doc()
.set({
name: action.payload.name,
uid: user.uid
})
.then(() => {
return { type: ADD_CATEGORY_SUCCESS }
})
.catch(err => {
return { type: ADD_CATEGORY_ERROR, payload: err }
})
})
}

现在我不仅要发送 ADD_CATEGORY_SUCCESS,还想刷新列表 (GET_CATEGORIES_REQUEST)。我尝试了很多东西,但总是得到

Actions must be plain objects. Use custom middleware for async actions

例如:

const addCategoryEpic = action$ => {
return action$.ofType(ADD_CATEGORY_REQUEST)
.switchMap((action) => {
const db = firebase.firestore()
const user = firebase.auth().currentUser
return db.collection('categories')
.doc()
.set({
name: action.payload.name,
uid: user.uid
})
.then(() => {
return Observable.concat([
{ type: ADD_CATEGORY_SUCCESS },
{ type: GET_CATEGORIES_REQUEST }
])
})
.catch(err => {
return { type: ADD_CATEGORY_ERROR, payload: err }
})
})
}

或者将 switchMap 更改为 mergeMap

最佳答案

问题是在你的 switchMap 里面你正在返回一个 Promise,它本身解析为一个 concat Observable; Promise<ConcatObservable> . switchMap operator 将监听 Promise,然后按原样发出 ConcatObservable,然后将其提供给 store.dispatch在 redux-observable 的引擎盖下。 rootEpic(action$, store).subscribe(store.dispatch) .由于分派(dispatch) Observable 没有意义,这就是为什么您会收到操作必须是普通对象的错误。

您的 epic 发出的内容必须始终是普通的旧 JavaScript 操作对象,即 { type: string } (除非你有额外的中间件来处理其他事情)

由于 Promises 只发出一个值,我们不能用它们发出两个 Action ,我们需要使用 Observables。因此,让我们首先将我们的 Promise 转换为我们可以使用的 Observable:

const response = db.collection('categories')
.doc()
.set({
name: action.payload.name,
uid: user.uid
})

// wrap the Promise as an Observable
const result = Observable.from(response)

现在我们需要将发出单个值的 Observable 映射到多个操作中。 map运算符不做一对多,相反我们想使用 mergeMap 之一, switchMap , concatMap , 或 exhaustMap .在这种非常特殊的情况下,我们选择哪一个并不重要,因为我们应用它的 Observable(包装了 Promise)只会发出一个值,然后 complete()。也就是说,了解这些运算符之间的区别至关重要,因此一定要花一些时间来研究它们。

我要使用 mergeMap (同样,在这种特定 情况下无关紧要)。自 mergeMap期望我们返回一个“流”(一个 Observable、Promise、迭代器或数组)我将使用 Observable.of为我们要发出的两个 Action 创建一个 Observable。

Observable.from(response)
.mergeMap(() => Observable.of(
{ type: ADD_CATEGORY_SUCCESS },
{ type: GET_CATEGORIES_REQUEST }
))

这两个 Action 将按照我提供的顺序同步和顺序发出。

我们也需要添加错误处理,所以我们将使用 catch来自 RxJS 的运算符——它与 catch 的区别Promise 上的方法很重要,但超出了这个问题的范围。

Observable.from(response)
.mergeMap(() => Observable.of(
{ type: ADD_CATEGORY_SUCCESS },
{ type: GET_CATEGORIES_REQUEST }
))
.catch(err => Observable.of(
{ type: ADD_CATEGORY_ERROR, payload: err }
))

把它们放在一起,我们会得到这样的东西:

const addCategoryEpic = action$ => {
return action$.ofType(ADD_CATEGORY_REQUEST)
.switchMap((action) => {
const db = firebase.firestore()
const user = firebase.auth().currentUser
const response = db.collection('categories')
.doc()
.set({
name: action.payload.name,
uid: user.uid
})

return Observable.from(response)
.mergeMap(() => Observable.of(
{ type: ADD_CATEGORY_SUCCESS },
{ type: GET_CATEGORIES_REQUEST }
))
.catch(err => Observable.of(
{ type: ADD_CATEGORY_ERROR, payload: err }
))
})
}

虽然这有效并回答了您的问题,但多个 reducer 可以通过同一个 Action 更改状态,而这通常是一个人应该做的。顺序发出两个 Action 通常是一种反模式。

也就是说,这在编程中很常见,这不是绝对规则。确实有一些时候单独执行更有意义,但它们是异常(exception)。您可以更好地了解这是否是这些异常(exception)情况之一。请记住这一点。

关于javascript - 如何从 redux-observable 调度多个 Action ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47965184/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com