2017-08-08 37 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