оператор yield* делегата в Redux Sagas

В Учебнике по Redux Sagas для начинающих нам предлагается написать наблюдатель Сага такая:

export function* watchIncrementAsync() {
   yield* takeEvery('INCREMENT_ASYNC', incrementAsync)
}

Почему мы используем оператор делегата yield* в строке 2, а не просто оператор yield? Разве они не сделают здесь одно и то же?


person AjaxLeung    schedule 04.08.2016    source источник
comment
Я предполагаю, что takeEvery возвращает итератор, а yield* делегирует этому итератору. Обычный yield просто вернул бы этот итератор вызывающей стороне.   -  person    schedule 04.08.2016
comment
Что было бы недостатком простого возврата итератора вызывающей стороне? В любом случае итератор запускается до тех пор, пока он не будет исчерпан, чего я и хочу.   -  person AjaxLeung    schedule 04.08.2016
comment
Вызывающий абонент, кажется, автоматически вызывает генератор. Возможно, это поведение характерно для Redux Sagas.   -  person AjaxLeung    schedule 05.08.2016


Ответы (2)


Как говорит LUH3417, takeEver ЯВЛЯЕТСЯ генератором, поэтому в этом случае вы уступаете (делегируете ему). Из документов:

function* takeEvery(pattern, saga, ...args) {
  while (true) {
    const action = yield take(pattern)
    yield fork(saga, ...args.concat(action))
  }
}

Я предполагаю, что речь идет о потоке управления. Если ваш итератор не заботится о том, чтобы выдать что-то еще, кроме takeEvery, то я не вижу причин, по которым вам нужно полностью выдать свой поток управления. Если вашему генератору необходимо передать управление другому генератору, а затем вернуться, то я вижу ценность передачи управления над... но в вашем примере я не вижу причины кода, по которой вам нужно делегировать управление, чтобы взятьКаждый . Если я не прав, пожалуйста, дайте мне знать.

person james emanon    schedule 04.08.2016
comment
Это не похоже на ответ на мой вопрос. Мне не нужно делегировать полномочия генератору, чтобы он продолжал работать, поэтому почему бы просто не использовать yield? - person AjaxLeung; 04.08.2016
comment
я предполагаю, что речь идет о потоке управления. Если ваш итератор не заботится о том, чтобы выдать что-то еще, кроме takeEvery, то я не вижу причин, по которым вам нужно полностью выдать свой поток управления. Если вашему генератору необходимо передать управление другому генератору, а затем вернуться, то я вижу ценность передачи управления над... но в вашем примере я не вижу причины кода, по которой вам нужно делегировать управление, чтобы взятьКаждый . Если я не прав, пожалуйста, дайте мне знать. - person james emanon; 05.08.2016

Эти две ссылки могут помочь объяснить:
http://yelouafi.github.io/redux-saga/docs/advanced/ComposingSagas.html
http://yelouafi.github.io/redux-saga/docs/advanced/SequencingSagas.html (эта страница была добавлена ​​сегодня)

Из сочинения саг:

yield* позволяет только последовательное составление задач, поэтому вы можете уступать* только одному генератору за раз

Я все еще пытаюсь понять все это сам, но, возможно, yield* с takeEvery означает, что с каждым последующим действием INCREMENT_ASYNC он вызывает подзадачу (incrementAsync в вашем примере), но делает это последовательно, как только предыдущая подзадача разрешилась. Если бы вы использовали yield, то для каждого действия INCREMENT_ASYNC он немедленно вызывал бы подзадачу, и они выполнялись бы и разрешались параллельно.

Использование takeLatest отличается от takeEvery тем, что отменяет предыдущий запрос для запуска нового.

person Will Schoenberger    schedule 12.08.2016
comment
Ссылки мертвы, не могли бы вы предоставить альтернативу, пожалуйста? - person Marecky; 28.02.2018