React Saga Yield 调用在下一段代码运行之前没有完成。

问题描述 投票:0回答:1

我这里有一个react传奇的代码,不按顺序运行。

yield put({ type: 'SHOW_LOADER', loading: 'workflowobject' }) #yield to initiate the loader
const states = yield call(() => axiosInstance.get(`/workflow-object/state/list/${action.workflow_id}/${action.workflow_object_id}/`))

const newState = states.data.map(item => ({    // some operation to shape my data , might this be the issue?
    iteration: item.iteration,
    ...item.state
}));

yield put({ type: "STORE_WORKFLOW_DATA", payload: newState , fetch: 'workflowobject' , label: 'states'})

.....
bunch more of yields here
.....
yield put({ type: 'HIDE_LOADER', loading: 'workflowobject' }) #yield to change loader state

这里的问题是 HIDE_LOADER 在一些中间操作结束之前被调用,导致我的组件中发现一个错误。

这是我的整个代码片段。

Saga

// This code loads the transitions and states for the detail page //
export function* workerWorkflowObjectDetail(action) {
    try{
    yield put({ type: 'SHOW_LOADER', loading: 'workflowobject' })
    // clears the object states
    yield put({ type: 'CLEAR_OBJECT_STATES' })
    // store workflow_id
    yield put({ type: "STORE_WORKFLOW_DATA", payload: action.workflow_id , fetch: 'workflowobject' , label: 'workflow_id'})
    const transitions = yield call(axiosInstance.get , `/workflow-object/transition/list/${action.workflow_id}/${action.workflow_object_id}/`)
    
    // store transitions
    yield put({ type: "STORE_WORKFLOW_DATA", payload: transitions.data, fetch: 'workflowobject' , label: 'transitions'})
    const newStateMap = {}
    transitions.data.forEach(transition => {
        if (transition.is_done) {
            newStateMap[transition.source_state] = done_class
            newStateMap[transition.destination_state] = selected_class
        } else if (transition.is_cancelled) {
            newStateMap[transition.destination_state] = cancelled_class
        } else {
            newStateMap[transition.destination_state] = default_class
        }
    });
   
    // store state_class_mapping
    yield put({ type: "STORE_WORKFLOW_DATA", payload: newStateMap, fetch: 'workflowobject' , label: 'state_class_mapping'})
    const states = yield call(axiosInstance.get, `/workflow-object/state/list/${action.workflow_id}/${action.workflow_object_id}/`)
    const newState = states.data.map(item => ({
        iteration: item.iteration,
        ...item.state
    }));
  
    // stores states
    yield put({ type: "STORE_WORKFLOW_DATA", payload: newState, fetch: 'workflowobject' , label: 'states'})
  
    // stores object_id
    yield put({ type: "STORE_WORKFLOW_DATA", payload: action.workflow_object_id, fetch: 'workflowobject' , label: 'object_identifier'})
    
    // stores current_state
    const current_state = yield call(axiosInstance.get,`/workflow-object/current-state/${action.workflow_id}/${action.workflow_object_id}/`)
    yield put({ type: "STORE_WORKFLOW_DATA", payload: current_state.data, fetch: 'workflowobject' , label: 'current_state'})
    
    //  stores current iteration
    const current_iteration = yield call(axiosInstance.get,`/workflow-object/current-iteration/${action.workflow_id}/${action.workflow_object_id}/`)
    yield put({ type: "STORE_WORKFLOW_DATA", payload: current_iteration.data, fetch: 'workflowobject' , label: 'current_iteration'})
    yield put({ type: 'HIDE_LOADER', loading: 'workflowobject' })
} catch(err){
 console.log(err)
}
    if (action.message) {
        yield put({ type: "CREATE_MESSAGE", message: action.message })
    }
}

减速器

// Helpers
const storeData = (state, action) => {
    switch (action.fetch) {
        case 'workflowobject': return loadWorkflowObject(state, action)
      
    }
}

const reducer = (state = initialState, action) => {
    switch (action.type) {
        case 'STORE_WORKFLOW_DATA': return storeData(state, action);
        case 'CLEAR_OBJECT_STATES': return clearObjectStates(state, action);
        default:
            return state;
    }
}

export default reducer;
reactjs redux redux-saga
1个回答
0
投票

根据 redux-saga 文件, call(fn, ...args) 函数应该提供一个普通函数或一个生成函数。

yield call(() => axiosInstance.get(`/workflow-object/state/list/${action.workflow_id}/${action.workflow_object_id}/`))

从你的代码来看,第一个参数既不是返回Promise的普通函数,也不是Generator函数。如果结果既不是Iterator对象,也不是Promise,中间件会立即将该值返回给saga,这样它就可以同步恢复执行。按照我的理解,这可能是问题所在。

所以,与其提供调用API的箭头函数,不如尝试提供这种方式。

yield call(axiosInstance.get, `/workflow-object/state/list/${action.workflow_id}/${action.workflow_object_id}/`)

希望这能帮助解决你所面临的问题。

© www.soinside.com 2019 - 2024. All rights reserved.