Я пытаюсь осуществить загрузку изображений через redux-сагу. Функции, которые мне нужно включить:
Лимит одновременных загрузок. Это достигается путем использования channel
как , описанного в саговой документации
Действие, которое я слушаю, START_UPLOADS
в приведенном ниже коде, содержит (возможно, довольно длинный) массив файлов, которые публикуются на канале отдельно.
Мне нужно иметь возможность отменить все текущие загрузки с помощью другого действия, CANCEL_ACTION
, включая те, которые поступили в каком-либо START_UPLOADS, но еще не были опубликованы на канале, а также те, которые в настоящее время обрабатываются в любом 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;
РЕДАКТИРОВАТЬ: перегонять в песочницу здесь: https://codesandbox.io/s/cancellable-counter-example-qomw6