我想在取消/关闭传奇故事或关闭频道之后执行代码。
这是一个简单的示例:
但是我所缺少的是在所有这些操作完成之后如何执行代码。(在此示例中,是简单的console.log
)
代码在这里:
const {
take, fork, put, call, delay, all, join,
} = require('redux-saga/effects');
const { channel, runSaga } = require('redux-saga');
function* doSomeExpensiveThing(citiesChannel) {
while (true) {
const payload = yield take(citiesChannel);
// do some expensive operation with each number
// simulated here with a random 0-1000ms delay
yield delay(Math.floor(Math.random() * Math.floor(10)) * 100);
console.log('Finished number: ', payload);
}
}
function* bootstrapSaga(numberOfWorkers) {
console.log('Bootrstrapping saga.');
// create a channel to queue all incoming numbers
const numbersQueue = yield call(channel);
const workers = [];
// create N worker 'threads' to receive items put into the queue
for (let i = 0; i < numberOfWorkers; i += 1) {
workers.push(yield fork(doSomeExpensiveThing, numbersQueue));
}
const allNumbers = Array.from(Array(10).keys());
// add all numbers to the queue
while (allNumbers.length > 0) {
yield put(numbersQueue, allNumbers.pop());
}
// yield join(workers);
// yield all(workers.map(w => w.toPromise()));
// console.log('NEVER HAPPENS');
}
function* mainSaga(numberOfWorkers = 3) {
console.log('Starting...');
yield call(bootstrapSaga, numberOfWorkers);
console.log('ALL DONE.'); // Y U NO WORK?? ¯\_(ツ)_/¯
}
runSaga({}, mainSaga, 5);
如果更容易,这里有一个可运行的版本: https://codesandbox.io/s/o40kl 确保在codeandbox上打开控制台
在此示例中,我尝试了一些操作,例如使用yield all(workers)
或yield join(workers)
。这些只是使console.log('ALL DONE')
工作的尝试。
问题:要对其进行修改,我必须对脚本进行哪些修改?
答案 0 :(得分:1)
更新:为了使其正常工作,我们需要在put
将工作人员完成的工作之后关闭渠道:
numbersQueue.close();
然后我们可以使用all
效果来等待所有任务解决:
yield all(workers.map(w => w.toPromise()));
创建一个效果描述,指示中间件执行以下操作: 并行运行多个效果,并等待它们全部完成。 这完全是标准Promise#all的相应API。
更新:我已经对此codesandbox进行了更新,并添加了必要的修改,以便您可以看到它按预期工作。