2017-02-23 104 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' 
     }) 
    ); 
相關問題