具有异步功能的Redux传奇调用会触发无限循环

时间:2018-07-25 08:43:38

标签: javascript redux react-redux redux-saga saga

我对redux saga有疑问。我已经写了一个包装器,但是该包装器无法与async动作一起使用。

通常,我的野鹿看起来像这样:

const myAsyncAction = async data => // Do async stuff

function* mySaga(action) {
  yield put({
    type: SET_LOADING
    payload: true
  })

  try {
    const result = yield call(myAsyncAction, action.payload)
    yield put({
      type: ACTION_SUCCESS
      payload: result
    })
  } catch (error) {
    console.log(error)
    yield put({
      type: SET_ERROR,
      payload: error
    })
    yield put({
      type: ACTION_FAIL
    })
  }

  yield put({
    type: SET_LOADING
    payload: false
  })
}

function* watchMySaga() {
  yield takeLatest(ACTION, mySaga)  
}

export default function* rootSaga() {
  yield all([
     watchMySaga()
  ])
}

如您所见,mySaga遵循一个模式。

首先,它通过将loading设置为true来告知应用程序正在执行异步操作。

之后,它将尝试执行异步操作。如果没有错误,则将ACTION_SUCCESS放入结果。如果发现错误,它将记录该错误并放入ACTION_FAIL

完成所有操作后,它将loading设置为false。

由于几乎所有的sagas都遵循这种模式,因此我认为将其中的一些抽象化是有意义的。我这样做的方法是编写一个包装器。

function* wrapper(saga, args) {
  let result

  yield put({
    type: SET_LOADING
    payload: true
  })

  try {
    result = yield call(saga, ...args)
  } catch (error) {
    console.log(error)
    yield put({
      type: SET_ERROR,
      payload: error
    })
  }

  yield put({
    type: SET_LOADING
    payload: false
  })

  return result
}

使用这个包装器,我期望像这样重写mySaga

function* mySaga(action) {
    const result = yield call(wrapper, myAsyncAction, [ action.payload ])
    yield put({
        type: result === undefined ? ACTION_FAIL : ACTION_SUCCESS,
        payload: result 
    })
}

如果myAsyncAction不是async,这实际上可以工作。常规功能将完美运行。但是,那对我没有太大帮助。

myAsyncAction确实是async的情况下,使用包装器将触发无限循环。

调试时,我注意到了这种情况。触发ACTION时,代码从观察程序运行到包装程序内部和async函数内部的传奇。它可以在异步操作中完美运行,直到达到await。当代码到达await时,出于某种原因再次调度ACTION,再次开始循环。

我不确定为什么会这样,我真的很好奇为什么会这样。

作为一种可能的解决方案,我正在考虑将ACTION_SUCCESSACTION_FAIL发送到包装器,并从返回结果更改为将其实际放入包装器中。

但是,我认为那是有限的,也许我不想发表结果,也许我想对它做其他事情。

您知道为什么会发生这种情况吗?有什么可能的解决方案?

谢谢!


TLDR:将yield call与异步功能一起使用时会陷入无限循环,因为到达await时,触发动作将再次分派。

0 个答案:

没有答案