2017-02-23 105 views
0

在redux-observable中,我需要等到执行一个API请求,直到另一个史诗已经完成。使用combineLatest不起作用,APP_INITIALIZED完成后没有任何反应。我也试着用最好的,但都不起作用。如何延迟一个史诗直到另一个史诗发出一个值

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

回答

2

一种方法是(使用假名),接收初始动作API_GET_REQUEST当你立即开始监听单INITIALIZE_FULFILLED,这标志着该初始化(或其他)具有completed--我们会实际启动一下。收到后,我们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' 
     }) 
    ); 

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


所有这一切说,如果你永远不要调用初始化除了在这个位置,你也只需要直接包括代码在单史诗本身,或者只是使抽象成为一个辅助函数。将它们保持为独立的史诗通常意味着您的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' 
     }) 
    ); 
相关问题