gpt4 book ai didi

javascript - 我如何在 redux-saga 中以有限的并发性和理智的取消来实现批处理任务?

转载 作者:行者123 更新时间:2023-11-30 11:03:51 27 4
gpt4 key购买 nike

我正在尝试通过 redux-saga 实现图片上传。我需要包括的功能是:

  • 并发上传限制。这是通过使用 channel 作为 described in saga docs 来实现的

  • 我收听的操作,START_UPLOADS 在下面的代码中,包含一个(可能很长)文件数组,这些文件单独发布到 channel 。

  • 我需要能够通过另一个操作 CANCEL_ACTION 取消所有当前上传,包括到达任何 START_UPLOADS 但尚未发布到 channel 的那些,以及那些当前正在任何 uploadImage worker 中处理。

我得到的代码如下。我的问题是 cancelAll 处理程序是在 finally block 之后执行的,它重新启动了传奇,而且我似乎需要重新启动所有内容。它看起来笨重且容易出错。您能否就这是否是 Sagas 的使用方式提供任何建议?

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;

编辑:在此处提炼到沙箱中:https://codesandbox.io/s/cancellable-counter-example-qomw6

最佳答案

我喜欢使用 race 来取消 - race 的解析值是一个具有一个键和一个值(“获胜”任务)的对象。 redux-saga race() docs

const result = yield race({
cancel: take(CANCEL_ACTION),
listener: call(listenToUploads), // use blocking `call`, not fork
});

if (result.cancel) {
yield call(cancelAll)
}

^ 这可以包含在 while (true) 循环中,因此您应该能够合并原始示例中重复的 fork()。如果需要重新安排工作人员,您可以考虑在 cancelAll 中进行处理。

我更喜欢让外部任务处理重新启动,而不是从它们自己的 finally block 中调用任务。

编辑:重构示例沙箱 https://codesandbox.io/s/cancellable-counter-example-j5vxr

关于javascript - 我如何在 redux-saga 中以有限的并发性和理智的取消来实现批处理任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56530161/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com