![](/img/trans.png)
[英]How do I sequence actions in RxJS/redux-observable vs redux-saga?
[英]How can I sequence redux actions after some async action completed in redux-observable?
我有很多形式的動作: LOAD_XYZ
, LOAD_XYZ_FAIL
, LOAD_XYZ_SUCCESS
用於需要加載的不同頁面元素。
我經常希望在加載某些項目后執行重定向( react-router
),但是由於redux-observable
不會返回諾言,所以我無法在組件中執行重定向-而是必須使用redux
和push('...')
來自react-router-redux
。
不幸的是,這導致大量重復,因為我有相同動作的LOAD_XYZ
和LOAD_XYZ_REDIRECT_TO
版本, LOAD_XYZ_REDIRECT_TO
版本都有兩個史詩。
這開始感到浪費,並且冗余過多
const fetchUserEpic = action$ =>
action$.ofType(FETCH_USER)
.mergeMap(action =>
ajax.getJSON(`https://api.github.com/users/${action.payload}`)
.map(response => fetchUserFulfilled(response))
);
const fetchUserAndRedirectEpic = action$ =>
action$.ofType(FETCH_USER_AND_REDIRECT)
.mergeMap(action =>
ajax.getJSON(`https://api.github.com/users/${action.payload}`)
.concatMap(response => [fetchUserFulfilled(response), push(action.redirectTo)])
);
是否有某種模式/方法,可以在某種異步請求完成后對要分派的動作進行排序,以避免冗余並必須實現同一史詩的多個版本。
例如,我希望有一個單獨的REDIRECT_TO
操作,可以在加載項目后對其進行排序。
類似於以下(虛構)解決方案:
dispatch(fetchUser(...)).then(redirectTo("..."))
dispatchSequence(fetchUser(...), redirectTo("..."))
我知道redux-thunk
可以做到這一點,但后來我錯過了所有rxjs運算符。
我可能正涉足危險地帶,但我確實找到了解決方法。
首先,我們制作一個中間件,該中間件將可觀察到的完成作為元數據添加到動作中。
import { Subject } from "rxjs";
export const AddListenerMiddleware = store => next => action => {
const forkedAction = Object.assign({}, action, { meta: { listener: new Subject()}});
next(forkedAction);
return forkedAction.meta.listener.asObservable();
};
由於這是一個Subject
我們可以在其上調用next
發出一些值。 創建notify
助手可以使我們將操作完成的時間通知所有訂閱者(以及傳遞數據)。
// notify doesn't consume but just emits on the completion observable
const notify = (action, fn) => source =>
Observable.create(subscriber =>
source.subscribe(emmission => {
if (action.meta && action.meta.listener) {
action.meta.listener.next(fn(emmission));
}
subscriber.next(emmission);
})
);
const fetchUserEpic = action$ =>
action$.ofType(FETCH_USER)
.mergeMap(action =>
ajax.getJSON(`https://api.github.com/users/${action.payload}`)
.map(response => fetchUserFulfilled(response))
.pipe(notify(action, response => response.data))
);
現在,我們的調度返回一個可觀察的對象,我們可以在該對象上執行標准的rxjs操作。 因此,這最終成為可能:
dispatch(fetchUser(...))
.subscribe(({id}) => dispatch(redirectTo("/" + id)))
免責聲明:使用風險自負!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.