javascript - 如何延迟一个史诗直到另一个史诗发出值

标签 javascript redux rxjs redux-observable

在 redux-observable 中,我需要在执行 API 请求之前等待,直到另一个史诗完成。使用 combineLatest 不起作用,APP_INITIALIZED 完成后没有任何反应。我也试过 withLatestFrom 但都不起作用。

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 });
          });
      })
  );
};

combineLatest definition

最佳答案

一种方法是(使用伪名称),当接收到初始操作 API_GET_REQUEST 时,您会立即开始监听单个 INITIALIZE_FULFILLED,这表明初始化(或其他任何) 已经完成——我们稍后会开始。收到后,我们 mergeMap(或 switchMap 以您的用例为准)进入我们的调用以发出其他 ajax 请求并执行通常的业务。最后,启动我们正在等待的实际初始化的技巧是在整个链的末尾添加 startWith()——这将发出和分派(dispatch)另一个史诗正在等待的 Action .

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'
        })
    );

您没有提到一切是如何工作的,所以这只是伪代码,您需要根据您的用例进行修改。


总而言之,如果您只在这个位置调用初始化,您也可以将该代码直接包含在单个史诗本身中,或者只创建一个对其进行抽象的辅助函数。将它们作为单独的史诗通常意味着您的 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'
        })
    );

关于javascript - 如何延迟一个史诗直到另一个史诗发出值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42426908/

相关文章:

javascript - 如何向页面加载后创建的 div 添加监听器?

javascript - 当前类 - mouseenter jQuery 动画

javascript - react /Redux : Where to put jQuery event handlers in component awaiting async data

redux - 在基于 Action /reducer 的应用程序中处理多个异步调用的加载状态

javascript - 如何在 for 循环中使用 .getElementsByClassName() 来隐藏 HTML 元素

javascript - 将 JavaScript 值以明文形式保存在数据库中

javascript - 如何将 JS Flow 类型与 Redux reducer 和 lodash 结合使用?

javascript - Angular 2 错误处理 - 发送到订阅的组件

javascript - 服务中的错误处理 - Angular 4

angular - 可观察类型错误 : cannot read property of undefined