Redux-Saga:是否有保证执行传奇的命令?

时间:2017-10-28 19:58:24

标签: javascript reactjs redux redux-saga

如果我在同一个动作上有两个传奇等待yield take(),那么是否有保证哪个传奇会首先获取动作并执行其剩余逻辑或是随机的?我需要确保第一个saga在第二个saga之前执行其逻辑。

function* rootSaga() {
    yield [ 
        saga1(),
        saga2()
    ]
}

function* saga1() {
    while (true) {
        //Random logic
        yield take("MY_ACTION")
        //Finish executing logic
    }
}

function* saga2() {
    while (true) {
        //Random logic
        yield take("MY_ACTION")
        //Finish executing logic
    }
}

2 个答案:

答案 0 :(得分:1)

你不能在这里依赖执行的顺序。当您的行动被调度时,所有已产生与该行动相匹配的take效果的传奇将立即恢复。如果执行的命令是"保证",那么这将是您不应该依赖的实施细节。

如果您需要在saga2执行saga1之后的逻辑后恢复"MY_ACTION",那么saga2应该真正等待的是另一个操作指示那个saga1已经完成了它的工作,而不是第一个工作。

function* rootSaga() {
  yield [ 
    saga1(),
    saga2()
  ]
}

function* saga1() {
  while (true) {
    //Random logic
    yield take("MY_ACTION")
    //Finish executing logic
    yield put({type: "MY_ACTION_DONE"})
  }
}

function* saga2() {
  while (true) {
    //Random logic
    yield take("MY_ACTION_DONE")
    //Finish executing logic
  }
}

答案 1 :(得分:1)

在执行必要的逻辑之后,您可以从初始的生成器调用或分叉依赖生成器,而不是两者都独立运行。

请注意callfork之间存在微妙但重要的区别。 call(saga2)正在阻塞,因此会暂停你的while循环,并且在saga2完成之前不再对"MY_ACTION"个动作做出反应,而fork(saga2)是非阻塞的,就像后台任务一样,所以会继续与你的循环恢复并行执行,这样你就可以继续响应更进一步的"MY_ACTION"

另外需要注意的是fork仍然附加到父级传奇,所以会随之取消,错误会从父级传递给父级等等。我想这是可取的但是如果你需要一个完整的无论父级传奇发生什么情况,将继续运行的分离版本,请使用spawn代替

function* rootSaga() {
    yield all([ 
        fork(saga1)
    ])
}

function* saga1() {
    while (true) {
        //Random logic
        const action = yield take("MY_ACTION")
        //Finish executing logic

        // BLOCKING `call` saga2, passing original action as param if needed
        yield call(saga2, action)

        // OR NON-BLOCKING `fork` saga2
        yield fork(saga2, action)

        // OR NON-BLOCKING DETACHED `spawn` saga2
        yield spawn(saga2, action)
    }
}

function* saga2(action) {
    // Do whatever dependant logic
    // safe in the knowledge that saga1 has done its job already
}