对取消的可观察

时间:2018-03-29 08:11:07

标签: redux rxjs redux-observable

您好,并提前致谢:)

主要想法

我想推出具体的动作$ 史诗来自redux-observable 取决于路线,并在路线更改时取消它们。 此外,我想在取消史诗时处理一些清理工作。我已经做了。但是:

问题

我使用 state.dispatch(actions.signInError({})) 进行清理(已弃用),并且不知道如何以其他方式执行 。我的代码在下面,问题就在最后。

更改路线时更改史诗

/**
 * Launch route specific actions if such exist and cancel previous one
 *
 * @param {Function} action$ - redux-observable action$
 * @param {Object} state - redux state
 */
const addEpicsForRoute = (action$, state) => action$
    .ofType(LOCATION_CHANGE) // action from route
    .switchMap(
        ( action ) => {
            // get epics for route
            const epicsForRoute = routeEpics[ action.payload.pathname ];

            if ( epicsForRoute ) {
                return merge(
                    ...epicsForRoute.map(observableCreator => observableCreator(action$, state))
                );
            } else {
                return empty(); // no specific epics
            }
        }
    );

某些路线的某些特定史诗

/**
 * Handle xhr request-response/error logic of sign in user
 *
 * @param {Function} action$
 * @param {Object} state
 */
export const signIn = ( action$, state ) => {
    return action$
        .ofType(types.SIGN_IN_REQUEST)
        .mergeMap(( { params, } ) => (
            Observable.create(observer => {
                services
                    .signInRequest( // it is ajax observable
                        mappers.mapSignInRequest(params)
                    )
                    .map(response => actions.signInJWTSuccess( // dispatch success
                        mappers.mapUser(response)
                    ))
                    .catch(error => of(actions.signInError( // dispatch error
                        mappers.mapSignInError(error)
                    )))
                    .subscribe(( value ) => { // pass action to redux-store
                        observer.next(value);
                    });

                return () => {
                    // cleanup logic. HERE IS A PROBLEM 
                    // calling store.dispatch() directly in your Epics is deprecated and will be removed.
                    // what should I use instead?
                    state.dispatch(actions.signInError({}));
                };
            })

        ));
};

此外,我是rxjs的新手,如果你有一个建议,我可以改进或使外观代码更漂亮,我感兴趣!

2 个答案:

答案 0 :(得分:0)

我建议查看代码流程,以充分利用Observables运算符的强大功能。

一个想法可能是沿着这些方向前进

signIn

通过这种方式,您创建了一个函数signIn,它返回一个Observable,它发出signIn ajax调用的结果。

然后,我会创建另一条逻辑来订阅const subscription = signIn(action, state) .subscribe( value => {// do what needs to be done with the result of the signIn call}, err => {// insert here the logic to handle error conditions}, () => {// do here what needs to be done when the Observable completes // consider that ajax calls complete after the first emit, therefore // you can put this part of logic also within the first callback, the one passed as the first parameter to subscribe() method } ) 返回的此类Observable,并决定做什么,例如

create

请注意,您还将订阅存储在变量中,您可以使用该变量在路线更改时取消订阅。

您放入cbrain_school方法返回的函数的清理逻辑可能会移动到您实际取消订阅订阅的位置,因为您移动到另一条路径。

答案 1 :(得分:0)

我认为一个好问题是这是否是正确的期望。当您使用switchMap时,您取消订阅内部Observable,这意味着您不再希望接收其排放。那么当您取消订阅时它会发出另一个动作是否有意义?

无论如何,你可以merge另一个只发出清理行为的链的Observable。

const action$ = new Subject();
const cleanup$ = new Subject();

action$
  .pipe(
    switchMap(() => new Observable(observer => {
      // whatever goes here
      observer.next('Observable created');

      return () => {
        cleanup$.next(/* create proper action here */ 'cleanup');
      };
    })),
    merge(cleanup$),
  )
  .subscribe(console.log);

action$.next(1);
action$.next(2);

我没有使用真正的redux-observable行动,但我希望你明白这一点。

现场演示(开放式控制台):https://stackblitz.com/edit/rxjs5-9iogn1?file=index.ts