问题描述
我这里有一个不按顺序运行的 react saga 代码:
I have a react saga code here which does not run in sequence:
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
在某些中间操作结束之前被调用,导致在我的组件中发现错误
The problem here is that the HIDE_LOADER
gets called before some inbetween operations end , leading to a error found in my component
这是我的整个代码片段:
Here is my entire code snippet:
// 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;
推荐答案
根据 redux-saga
documentation, call(fn, ...args)
函数应提供普通或生成器函数.
As per redux-saga
documentation, call(fn, ...args)
function should be provided with either a normal or a Generator function.
yield call(() => axiosInstance.get(`/workflow-object/state/list/${action.workflow_id}/${action.workflow_object_id}/`))
从您的代码看来,第一个参数既不是返回 Promise 的普通函数,也不是生成器函数.如果结果既不是 Iterator 对象也不是 Promise,中间件将立即将该值返回给 saga,以便它可以同步恢复执行.根据我的理解,这可能是问题所在.
From you code it looks like the first parameter is neither a normal function that is returning a Promise nor a Generator function. If the result is not an Iterator object nor a Promise, the middleware will immediately return that value back to the saga, so that it can resume its execution synchronously. As per my understanding this could be the issue.
因此,与其提供调用 API 的箭头函数,不如尝试提供这种方式,
So instead of providing the arrow function which is calling the API, try providing this way,
yield call(axiosInstance.get, `/workflow-object/state/list/${action.workflow_id}/${action.workflow_object_id}/`)
希望这有助于解决您面临的问题.
Hope this helps in resolving the issue which you are facing.
这篇关于React Saga Yield 调用在下一个代码运行之前没有完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!