Javascript 如何在redux saga中以有限的并发性和合理的取消实现批处理任务?
我试图通过redux saga实现图像上传。我需要包括的功能包括:Javascript 如何在redux saga中以有限的并发性和合理的取消实现批处理任务?,javascript,reactjs,asynchronous,react-redux,redux-saga,Javascript,Reactjs,Asynchronous,React Redux,Redux Saga,我试图通过redux saga实现图像上传。我需要包括的功能包括: 并发上传限制。这是通过使用频道实现的 我在下面的代码中听到的动作,START\u UPLOADS,包含一个单独发布到频道的文件数组(可能相当长) 我需要能够通过另一个操作取消所有当前上传,cancel\u action,包括在任何开始上传中到达但尚未发布到频道的上传,以及当前在任何uploadImage工作人员中处理的上传 我得到的代码如下。我的问题是,cancelAll处理程序在重新启动传奇的finally块之后执行,而我
- 并发上传限制。这是通过使用
实现的频道
- 我在下面的代码中听到的动作,
,包含一个单独发布到频道的文件数组(可能相当长)START\u UPLOADS
- 我需要能够通过另一个操作取消所有当前上传,
,包括在任何开始上传中到达但尚未发布到频道的上传,以及当前在任何cancel\u action
工作人员中处理的上传uploadImage
cancelAll
处理程序在重新启动传奇的finally
块之后执行,而我似乎需要重新启动一切。它看起来笨重而且容易出错。你能就这是否就是传说的用意给出一些建议吗
function* uploadImage(file) {
const config = yield getConfig();
const getRequest = new SagaRequest();
console.log("Making async request here.");
}
function* consumeImages(uploadRequestsChannel) {
while (true) {
const fileAdded = yield take(uploadRequestsChannel);
// process the request
yield* uploadImage(fileAdded);
}
}
function* uploadImagesSaga() {
const CONCURRENT_UPLOADS = 10;
const uploadRequestsChannel = yield call(channel);
let workers = [];
function* scheduleWorkers() {
workers = [];
for (let i = 0; i < CONCURRENT_UPLOADS; i++) {
const worker = yield fork(consumeImages, uploadRequestsChannel);
workers.push(worker);
}
}
let listener;
yield* scheduleWorkers();
function* cancelAll() {
// cancel producer and consumers, flush channel
yield cancel(listener);
for (const worker of workers) {
yield cancel(worker);
}
yield flush(uploadRequestsChannel);
}
function* putToChannel(chan, task) {
return yield put(chan, task);
}
function* listenToUploads() {
try {
while (true) {
const { filesAdded } = yield take(START_UPLOADS);
for (const fileAdded of filesAdded) {
yield fork(putToChannel, uploadRequestsChannel, fileAdded);
}
}
} finally {
// if cancelled, restart consumers and producer
yield* scheduleWorkers();
listener = yield fork(listenToUploads);
}
}
listener = yield fork(listenToUploads);
while (true) {
yield take(CANCEL_ACTION);
yield call(cancelAll);
}
}
export default uploadImagesSaga;
function*上传图像(文件){
const config=yield getConfig();
const getRequest=new SagaRequest();
log(“在此发出异步请求”);
}
函数*consumeImages(上传请求){
while(true){
const fileAdded=收益率(UploadRequestsAnnel);
//处理请求
产量*上传图像(添加文件);
}
}
函数*uploadImagesSaga(){
const CONCURRENT_UPLOADS=10;
const uploadRequestsChannel=收益调用(通道);
让工人=[];
函数*scheduleWorkers(){
工人=[];
for(设i=0;i
编辑:蒸馏到沙箱中:我喜欢使用
race
取消-比赛的解析值是一个具有一个键和一个值的对象(“获胜”任务)
^这可以包装在while(true)
循环中,因此您应该能够合并原始示例中重复的fork()。如果工人需要重新安排,你可以考虑在代码> > CuffelAu/<代码>内处理。< /P>
我更喜欢让外部任务处理重新启动,而不是从它们自己的finally
块调用任务
编辑:重构示例沙盒谢谢,我会试试的。我把这个问题提炼成一个沙箱:我目前的主要问题是,取消工人仍然会导致虚假承诺成功完成。
cancel()
不应该阻止这种情况吗?异步任务中我最喜欢的部分之一是它提供了手动状态管理的替代方案。因此,对我来说,重构的时机已经成熟。在这个例子中,我把事情弄混了一点:---工作人员自己处理取消,所以他们不需要被终止/重新初始化。我们执行一个清理任务,在每个CANCEL
上清除通道,然后saga只侦听批上载事件。希望有帮助!这太棒了!非常感谢,这正是我在这个问题上需要的。
const result = yield race({
cancel: take(CANCEL_ACTION),
listener: call(listenToUploads), // use blocking `call`, not fork
});
if (result.cancel) {
yield call(cancelAll)
}