2017-08-08 64 views
0

我從API獲取用戶並將其存儲在我的狀態中,因此我不必再次獲取它。 問題是多個組件同時請求用戶導致多個併發提取請求。Redux sagas當多次發送同一個ID時只讀取一次

是否有避免這種情況的良好模式?

這是我的傳奇

function* watchUserRequests() { 
    yield takeEvery(actionTypes.USER_REQUESTED, userRequested); 
} 

function* userRequested(action) { 
    const {id} = action.payload; 
    let user = yield select(state => state.users.all[id]); 
    // cancel if user exists  
    if (user) return; 
    user = yield call(userApi.get, id); 
    yield put(userActions.userLoaded(id, banner)); 
} 

操作

export function userRequested(id) { 
    return {type: types.USER_REQUESTED, payload: {id}}; 
} 

export function userLoaded(id, user) { 
    return {type: types.USER_LOADED, payload: {id, user}}; 
} 
+0

爲了避免併發的取指令請求您可以在狀態存儲不僅牽強用戶還有那些正在取出。我可以看到這是不是很漂亮,但想不出一種方法來避免這種情況。你可以寫一些高階函數來至少隔離一些邏輯。 –

+0

謝謝,這是一個好主意。我試圖在userRequested函數開始時分派USER_LOADING操作來存儲這些信息。但是,所有的USER_REQUESTED操作都更快,並且在第一個USER_LOAD操作到達減速器之前就已經開始了。 – Fredrik

+0

您必須更改reducer中userRequested操作的狀態。 –

回答

0

這是我在另一個傳奇解決了這個問題。 「類型」在這裏可以忽略不計

  • 累積請求ID在IDS對象:
  • 派遣行動來獲取所有累積的IDS
  • 防抖取爲50毫秒
  • 在等待...添加新的IDS到IDS對象
  • 在等待......取消取任務給你50個新毫秒
  • 凱明取
  • 清除任務和IDS

代碼:

let ids = {}; 
let tasks = {}; 

function* watchCounterRequests() { 
    yield takeEvery(actionTypes.COUNTER_REQUESTED, accumulate); 
} 

function* watchCounterFetchRequests() { 
    yield takeEvery(actionTypes.COUNTER_FETCH_REQUESTED, counterFetchRequested); 
} 

function* accumulate(action) { 
    const {id, type} = action.payload; 
    if (!ids[type]) ids[type] = {}; 

    ids[type][id] = true; 
    if (tasks[type]) { 
    yield cancel(tasks[type]); 
    } 
    tasks[type] = yield fork(fetchCounters, type); 
} 

function* fetchCounters(type) { 
    yield call(delay, 50); 

    yield put({ 
    type: actionTypes.COUNTER_FETCH_REQUESTED, 
    payload: {type: type, ids: Object.keys(ids[type])}, 
    }); 

    delete ids[type]; 
    delete tasks[type]; 
} 

function* counterFetchRequested(action) { 
    const {ids, type} = action.payload; 
    let typeName = type + 'Ids'; 
    let req = { 
    [typeName]: ids 
    }; 
    yield put(counterActions.loadCounters(req)); 
} 

export default [watchCounterRequests, watchCounterFetchRequests]; 

這其中大部分來自這裏:https://marmelab.com/blog/2016/10/18/using-redux-saga-to-deduplicate-and-group-actions.html