我有以下(第一次)传奇:
export function* getIdentificators() {
while (true) {
yield take(GetIdentificators);
try {
const res = yield call(api.getIds);
const data = // some array of data
for (const elem of data) {
yield put(getAnotherStuff(elem)); <--- calling the second saga in a loop
}
}
}
}
如您所见,它会在for of
循环中调度某些操作。
它的工作正常,我的意思是 - 这个传奇被称为data
长度的多次。
这里有第二个传奇,负责处理getAnotherStuff
行动:
export function* anotherStuff() {
while (true) {
const action = yield take(someAction);
const { actionId } = action;
try {
const { data } = yield call(apiCall, elem);
yield put(someSuccessAction(Action, data));
}
}
}
所以 - 它不能正常工作。如果我将console.log
放入其中,则只会记录一次并且只显示第一个结果。因此它并不像我希望的那样工作(我希望它能像我在第一个传奇中一样多次工作)。
但,如果我改为使用takeEvery
:
export function* anotherStuffWatcher() {
yield takeEvery(someActionType, anotherStuff);
}
工作正常 - 正在处理所有请求。
我的最后一个问题 - 为什么我使用while(true)
它只处理第一个请求而不是每一个请求?为什么我使用takeEvery
时它能正常工作?谢谢!
答案 0 :(得分:1)
仅记录一次
这是因为call
阻止了效果。假设apiCall
需要一些时间。因此,当这个电话正在发生时,你的传奇被封锁,并没有采取新的行动。
export function* anotherStuff() {
while (true) {
const action = yield take(someAction);
const { actionId } = action;
try {
const { data } = yield call(apiCall, elem); // this is blocking call
yield put(someSuccessAction(Action, data));
}
}
}
为了避免这种情况,您可以使用takeEvery
帮助程序来处理与模式匹配的“采取一切”操作。或者您可以使用actionChannel
缓冲未来的行动
export function* anotherStuff() {
// buffers up to 10 actions
// or you could provide another buffering strategy via
// second argument https://redux-saga.js.org/docs/api/#buffers
const someChannel = yield actionChannel(someAction);
while (true) {
const action = yield take(someChannel);
const { actionId } = action;
try {
const { data } = yield call(apiCall, elem); // this is blocking call
yield put(someSuccessAction(Action, data));
} catch(blackhole) {}
}
}