0

我做了一個包裝,用於通過身份驗證頭訪問'rxjs/observable/dom/ajax'函數。那部分還行。我該如何使用rxjs儘早逃脫一個catch鏈?

export const authjax = { 
    create: urlOrRequest => ajax(typeof urlOrRequest === 'string' 
    ? {url: urlOrRequest, headers: authHeader()} : _.merge({}, urlOrRequest, {headers: authHeader()}) 
), 
    get: (url, headers = {}) => ajax.get(url, {...headers, ...authHeader()}), 
    post: (url, body = {}, headers = {}) => ajax.post(url, body, {...headers, ...authHeader()}), 
    put: (url, body = {}, headers = {}) => ajax.put(url, body, {...headers, ...authHeader()}), 
    patch: (url, body = {}, headers = {}) => ajax.patch(url, body, {...headers, ...authHeader()}), 
    getJSON: (url, headers = {}) => ajax.getJSON(url, {...headers, ...authHeader()}) 
}; 

所以,這是用來代替ajax。這是一個在史詩中使用的例子。

export const getBatchesEpic = (action$, store) => 
    action$.ofType(actions.GET_BATCHES) 
    .switchMap(action => { 
     const {paginate, refresh} = action; 
     const paginatorNext = _.get(store.getState(), 'manager.paginator.batches.next'); 
     const usePaginatorNext = paginatorNext && paginate && !refresh; 
     return authjax.get(usePaginatorNext ? paginatorNext : `${API_URL}/batches/`) 
     .concatMap(({response}) => { 
      const incompleteBatches = response.results.filter(batch => !batch.completed); 
      const checkBatchActions = incompleteBatches.map(batch => checkBatch(batch.id)); 
      return [ 
      {type: actions.BATCHES_RECEIVED, data: response, next: response.next, paginate}, 
      ...checkBatchActions 
      ]; 
     }) 
     .catch(error => Observable.of({type: actions.GET_BATCHES_ERROR, error}) 
    ); 
    }); 

現在,我在試圖使只使用authjax.get方法簡單的測試通過的第一階段。我希望401服務器的響應被authjax抓住,authjax返回一個註銷動作,以及取消任何下面的鏈接方法。

這是我的最新嘗試authjax.get。它適用於成功的Ajax響應,以及非401 ajax響應。它不返回任何東西,甚至註銷動作,當它擊中401

export const authjax = { 
    create: urlOrRequest => ajax(typeof urlOrRequest === 'string' 
    ? {url: urlOrRequest, headers: authHeader()} : _.merge({}, urlOrRequest, {headers: authHeader()}) 
), 
    get: (url, headers = {}) => { 
    const call = ajax.get(url, {...headers, ...authHeader()}); 

    return call.catch(error => { 
     if (_.get(error, 'status') === 401) { 
     console.log('401!!!', Observable.of({type: actions.LOGOUT})); 
     return Observable.of({type: actions.LOGOUT}).ignoreElements(); 
     } 
     return call; 
    }); 

    }, 
    post: (url, body = {}, headers = {}) => ajax.post(url, body, {...headers, ...authHeader()}), 
    put: (url, body = {}, headers = {}) => ajax.put(url, body, {...headers, ...authHeader()}), 
    patch: (url, body = {}, headers = {}) => ajax.patch(url, body, {...headers, ...authHeader()}), 
    getJSON: (url, headers = {}) => ajax.getJSON(url, {...headers, ...authHeader()}) 
}; 

我讀rxjs文檔,但發現沒有,你會不會需要轉出或取消的假設流中的流。我知道有些選項可以在Epic本身中處理更多,但我希望authjax能夠處理自己的身份驗證問題,因此我可以將它用作使用相同身份驗證的多個應用程序的導入。

+0

我不得不做幾次 - 根據concatMap裏面的結果取消所有concatMap的等待請求。我最近回答了一個類似的問題:https://stackoverflow.com/questions/44496395/rxjs-chain-observables-completing-at-any-point/44505681#44505681 –

+0

壓縮不適合我,因爲我必須完成任何從authjax返回之前返回它,所以我不能將以下鏈接的方法添加到zip。 我在返回的observable上嘗試過.ignoreElements(),但它也忽略了我返回的第一個元素,它只拾取鏈中的錯誤相關事件。如果我拋出一個錯誤,然後鏈接.ignoreElements,我的catch語句將在鏈中觸發。 我可能會試圖讓rxjs做一些它不應該做的事情。 – Sally

回答

0

這是我現在想出的答案。

export const wrapAjax = ({method, args = {}}) => { 
    const headers = {...args.headers || {}, ...authHeader()}; 

    const call = method 
    ? ajax[method](..._.values(_.omit(args, ['headers'])), headers) 
    : ajax(_.merge({}, args, {headers})); 

    return call.catch(error => { 
    if (_.get(error, 'status') === 401) { 
     return Observable.throw({...error, action: {type: actions.AUTH_401, error}}).ignoreElements(); 
    } 
    return call; 
    }); 
}; 

它停止任何鏈方法,如果狀態是401,並且命中任何後來的catch語句。史詩中的catch語句很遺憾地不得不分發返回的action屬性。不開玩笑,但這是我現在結束了。