如何将一部史诗片延迟到另一部史诗片发出价值

ddc*_*432 3 javascript rxjs redux redux-observable

在redux-observable中,我需要等待执行API请求,直到另一个史诗完成。使用CombineLatest不起作用,在APP_INITIALIZED完成后什么也没有发生。我也尝试了用LatestFrom,但是都没有用。

const apiGetRequestEpic = (action$, store) => {
  return Observable.combineLatest(
    action$.ofType('APP_INITIALIZED'),
    action$.ofType('API_GET_REQUEST')
      .mergeMap((action) => {
        let url = store.getState().apiDomain + action.payload;
        return ajax(get(url))
          .map(xhr => {
            return {type: types.API_RESPONSE, payload: xhr.response};
          })
          .catch(error => {
            return Observable.of({ type: 'API_ERROR', payload: error });
          });
      })
  );
};
Run Code Online (Sandbox Code Playgroud)

Combine最新定义

jay*_*lps 6

一种方法是(使用伪名称),当您收到初始操作时,API_GET_REQUEST您立即开始侦听单个INITIALIZE_FULFILLED信号,这表明初始化(或任何其他方式)已完成-实际上,我们将稍等一下。收到消息后,我们mergeMap(或switchMap您所用的任何一种情况)都会在我们的调用中发出另一个ajax请求并进行常规业务。最后,启动我们正在等待的实际初始化的技巧是startWith()在整个链的末尾添加一个-它将发出并调度另一个史诗正在等待的动作。

const initializeEpic = action$ =>
  action$.ofType('INITIALIZE')
    .switchMap(() =>
      someHowInitialize()
        .map(() => ({
          type: 'INITIALIZE_FULFILLED'
        }))
    );

const getRequestEpic = (action$, store) =>
  action$.ofType('API_GET_REQUEST')
    .switchMap(() =>
      action$.ofType('INITIALIZE_FULFILLED')
        .take(1) // don't listen forever! IMPORTANT!
        .switchMap(() => {
          let url = store.getState().apiDomain + action.payload;
          return ajax(get(url))
            .map(xhr => ({
              type: types.API_RESPONSE,
              payload: xhr.response
            }))
            .catch(error => Observable.of({
              type: 'API_ERROR',
              payload: error
            })); 
        })
        .startWith({
          type: 'INITIALIZE'
        })
    );
Run Code Online (Sandbox Code Playgroud)

您没有提到一切如何工作,因此这只是伪代码,您需要针对用例进行修改。


话虽如此,如果您除了在此位置之外从未调用过该初始化,还可以直接将该代码直接包含在单个史诗本身中,或者仅创建一个抽象它的辅助函数。将它们保留为单独的史诗通常意味着您的UI代码可以独立触发它们中的任何一个-但出于测试目的将它们分开可能仍然很好。只有您可以拨打电话。

const getRequestEpic = (action$, store) =>
  action$.ofType('API_GET_REQUEST')
    .switchMap(() =>
      someHowInitialize()
        .mergeMap(() => {
          let url = store.getState().apiDomain + action.payload;
          return ajax(get(url))
            .map(xhr => ({
              type: types.API_RESPONSE,
              payload: xhr.response
            }))
            .catch(error => Observable.of({
              type: 'API_ERROR',
              payload: error
            }));
        })
        .startWith({ // dunno if you still need this in your reducers?
          type: 'INITIALIZE_FULFILLED'
        })
    );
Run Code Online (Sandbox Code Playgroud)