redux-saga 中的 takeSequential?

takeSequential in redux-saga?

我有一个基本的传奇,如下所示:

const mySaga = function* () {
    yield takeEvery("SOME_ACTION_REQUEST", function* (action) {

        const result = yield call(makeApiCall, action.payload); 
        yield put({
            type: "SOME_ACTION_SUCCESS", 
            payload: result
        }); 

    });  
}

现在我遇到的问题是,如果我同时调度了两个 "SOME_ACTION_REQUEST",那么我会遇到 redux 调用堆栈如下所示的情况:

SOME_ACTION_REQUEST
SOME_ACTION_REQUEST
SOME_ACTION_SUCCESS
SOME_ACTION_SUCCESS

这搞砸了我的减速器中的逻辑。

我想要的是每个请求都是 运行,但要等待前一个请求完成才能开始。

即。所以它看起来像:

SOME_ACTION_REQUEST
SOME_ACTION_SUCCESS
SOME_ACTION_REQUEST
SOME_ACTION_SUCCESS

我该如何实现?

可以使用 actionChannel 效果来实现这一点。

参见:https://redux-saga.js.org/docs/api/#actionchannelpattern-buffer

const mySaga = function* () {
    const channel = yield actionChannel("SOME_ACTION_REQUEST"); 
    while (true) {
        const action = yield take(channel); 
        const result = yield call(makeApiCall, action.payload); 
        yield put({
            type: "SOME_ACTION_SUCCESS", 
            payload: result
        }); 
    }
}

解释:

我的理解是 actionChannel 效果只是将匹配该模式的所有传入请求路由到队列中。

take 效果会把它们弹开。

将其全部放在 while(true) 循环中意味着操作将一次弹出一个,它们需要等待解决所有其他事情(API调用)才能调用下一个。

关于此模式需要注意的一件事是,在 redux-dev-tools 中,redux 堆栈仍将如下所示:

SOME_ACTION_REQUEST
SOME_ACTION_REQUEST
SOME_ACTION_SUCCESS
SOME_ACTION_SUCCESS

因为请求会立即添加到频道并保持不活动状态,直到它们被弹出。

您只需执行两个分叉任务即可实现此目的。就像一个乒乓消息系统。

对于 takeEvery 始终为收到的每个操作创建一个新的分叉任务。

像这样:

function* ping() {
  while (true) {
    const { payload } = yield take("SOME_ACTION_REQUEST");
    yield put({
      type: "DO_REQUEST", 
      payload
    });
    yield take("SOME_ACTION_SUCCESS");
  }
}

function* pong() {
  while (true) {
    const { payload } = yield take("DO_REQUEST");
    const result = yield call(makeApiCall, payload); 
    yield put({
      type: "SOME_ACTION_SUCCESS", 
      payload: result
    }); 
  }
}

function* rootSaga() {
  yield all([
    fork(ping),
    fork(pong),
  ]);
}