Redux Saga: Как дождаться появления и вызова, чтобы не блокировать родительский вызов

1

Я пытаюсь добавить функцию саги Redx, но я не могу получить правильную цепочку

const randomDelay = () => parseInt(Math.random() * 500)
const a = function*() {
   yield spawn(b)
   yield call(c)
}
const b = function*() {
   yield delay(randomDelay())
}
const c = function*() {
   yield delay(randomDelay())
}
const d = function*() {}
  • Я хочу вызвать a который будет порождать b и вызывать c.
  • Когда c завершением я хочу стать разблокированы и полными. a
  • Когда b и c оба завершены, я хочу позвонить d

Из того, что я могу сказать, нет способа сделать это. all или fork будет блокировать a

Чтобы обойти это сейчас, я вызвал c первым и создал b и d после, но это означает, что b и c не могут работать одновременно.

Теги:
redux
redux-saga

2 ответа

0

Не так элегантно, как qaru.site/questions/16829778/....

Также мой ответ предполагает, что a выполняет только вызовы b и c (или только две задачи).

import { delay } from "redux-saga";
import { all, cancel, put, takeEvery, spawn, call } from "redux-saga/effects";

const randomDelay = () => parseInt(Math.random() * 500);

export function* startTasks() {
  let completed = yield call(a);

  if (completed) {
    yield call(d);
  }
}

const a = function*() {
  let b_finished = false;
  const b = function*() {
    yield delay(randomDelay());
    yield put({ type: "B_DONE" });
    b_finished = true;
  };

  const c = function*() {
    yield delay(randomDelay());
    yield put({ type: "C_DONE" });
  };

  const taskB = yield spawn(b);
  yield call(c);
  yield cancel(taskB);
  return b_finished;
};

const d = function*() {
  yield delay(randomDelay());
  yield put({ type: "D_DONE" });
};

export function* watchStartTasks() {
  yield takeEvery("START_TASKS", startTasks);
}

export default function* rootSaga() {
  yield all([watchStartTasks()]);
}
  • 0
    Отмена b не является частью желаемого поведения.
  • 0
    Да ты прав. Я упоминал в ответе. Also my answer assumes a does the job of just calling b and c , поэтому отмена B будет означать отмену A
0

Для этого вам понадобится отдельный сигнальный механизм. Я бы использовал channel для этого.

  • первый создает канал
  • порождает dScheduler прохождение канала
  • a передает канал в качестве аргумента b
  • b делает put на канал в конце
  • a делает put в канал в конце (когда заканчивается c)
  • dScheduler делает два take канала и затем вызывает d

Код будет выглядеть примерно так:

import { delay, channel } from "redux-saga";
import { spawn, call, put, take } from "redux-saga/effects";

const randomDelay = () => parseInt(Math.random() * 500);
const B_OR_C_COMPLETED = "B_OR_C_COMPLETED";
export const a = function*() {
  const bcCompletedChannel = channel();
  yield spawn(dScheduler, bcCompletedChannel);
  yield spawn(b, bcCompletedChannel);
  yield call(c);
  yield put(bcCompletedChannel, B_OR_C_COMPLETED);
};
const b = function*(bcCompletedChannel) {
  yield delay(randomDelay());
  yield put(bcCompletedChannel, B_OR_C_COMPLETED);
};
const c = function*() {
  yield delay(randomDelay());
};
const dScheduler = function*(bcCompletedChannel) {
  yield take(bcCompletedChannel);
  yield take(bcCompletedChannel);
  yield call(d);
};
const d = function*() {
};

Здесь добавлен CodeSandbox с журналами консоли и увеличена задержка для упрощения проверки поведения:

Изображение 10034

Соответствующая часть документации Redux Saga находится здесь. В частности, раздел внизу называется "Использование каналов для связи между сагами".

Ещё вопросы

Сообщество Overcoder
Наверх
Меню