如果我使用以下形式的传奇:
function * sagaWorker() {
yield put(START_ACTION)
yield take(WAIT_FOR_ACTION)
yield delay(100)
yield put(END_ACTION)
}
我可以像这样使用runSaga
成功地测试它:
step('saga passes the tests', async () => {
const channel = stdChannel()
const dispatched = []
const options = {
dispatch: action => dispatched.push(action),
getState: () => {},
channel
}
const task = runSaga(options, sagaWorker)
channel.put(WAIT_FOR_ACTION)
await task.toPromise()
expect(dispatched).to.deep.eql([START_ACTION, END_ACTION])
})
但是,如果我将延迟时间移到汇整的前面:
function * sagaWorker() {
yield put(START_ACTION)
yield delay(100)
yield take(WAIT_FOR_ACTION)
yield put(END_ACTION)
}
现在,传奇故事没有完成并超时-它到达了take
,但动作从未到达频道。
是否可以使用此表格进行测试?我怀疑我可以通过call
而不是delay
直接yield
来使它们工作,但是我想知道如何不这样做而使它工作(如果可能的话) )。
答案 0 :(得分:4)
使用yield call(() => myPromiseyDelay(500))
不会在这里保存您。派遣时仍然没有什么可以注意到“丢失”的动作。
发布WAIT_FOR_ACTION
时,传奇故事在yield delay
上处于屈服状态。这里没有行动的队列,因此到yield take(WAIT_FOR_ACTION)
为止,WAIT_FOR_ACTION
行动早已被分派,您上面提到的任何佐贺逻辑都没有注意到(没有有效的{ {1}}进行操作。
请考虑设置一个actionChannel
来捕获这些未监听的操作。 take
完成后,它们将在渠道中排队等待使用。
所以,像这样:
delay
因此,将所有内容组合为非伪代码:
function * sagaWorker() {
const channel = yield actionChannel(WAIT_FOR_ACTION)
yield put(START_ACTION)
yield delay(100)
yield take(channel)
yield put(END_ACTION)
}
const {
runSaga,
stdChannel,
effects: {
take,
put,
actionChannel,
delay
}
} = window.ReduxSaga
const WAIT_FOR_ACTION = "WAIT_FOR_ACTION";
const START_ACTION = "START_ACTION";
const END_ACTION = "END_ACTION";
(async() => {
const channel = stdChannel();
const dispatched = [];
const options = {
dispatch: action => dispatched.push(action),
getState: () => {},
channel
};
const task = runSaga(options, sagaWorker);
channel.put({
type: WAIT_FOR_ACTION
});
await task.toPromise();
console.log(dispatched);
})();
function* sagaWorker() {
const channel = yield actionChannel(WAIT_FOR_ACTION);
yield put({
type: START_ACTION
});
yield delay(100);
yield take(channel);
yield put({
type: END_ACTION
});
}