Как запустить синхронный код после закрытия канала Sasex - PullRequest
2 голосов
/ 18 июня 2019

Я пытаюсь выполнить код после отмены / закрытия саги или после закрытия канала.

Это простой пример:

  1. Создать канал, которыйсодержит несколько случайных чисел
  2. Создайте несколько вилок для выполнения дорогостоящих вычислений для каждого числа.
  3. Добавьте несколько случайных чисел в канал
  4. После закрытия канала я хочувыполнить некоторый код.

Но мне не хватает только того, как выполнить код после того, как все это закончено. (в данном примере простой 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 Обязательно откройте консоль на кодыandbox

Для этогоНапример, я попробовал несколько вещей, таких как yield all(workers) или yield join(workers).Это были просто попытки заставить console.log('ALL DONE') работать.

Вопрос: Что мне нужно изменить в моем сценарии, чтобы он это сделал?

1 Ответ

1 голос
/ 19 июня 2019

Обновление : чтобы это работало, нам нужно закрыть канал после put работы, которую должны выполнить работники:

numbersQueue.close();

Тогда мы можем использовать эффект all для ожидания решения всех задач:

yield all(workers.map(w => w.toPromise()));

Создает описание эффекта, которое инструктирует промежуточное ПО Запустите несколько эффектов параллельно и дождитесь завершения всех из них. Это вполне соответствует API стандартному Promise # all.

Обновление : я обновил этот codesandbox и добавил необходимые модификации, чтобы вы могли видеть, что он работает должным образом.

enter image description here

...