03. Generator Execution

Использование генератора состоит из двух частей:

  1. Описании функции генератора function* generatorFunction();

  2. Получение объекта генератора generator.

// Generator function
function* generatorFunction() {
    ...
}

// Generator object
const generator = generatorFunction();

Вызов функции-генератора не начинает какое-либо выполнение, а возвращает новый объект генератора (generator object).

  • Каждый вызов функции-генератора порождает новый объект генератора, независимый от других.

  • Объект генератора ассоциирован с конкретным вызовом функции генератора (runtime call).

Generator Object

Объект генератора используется для того, что бы контролировать исполнение функции-генератора.

  • Метод generator.next() выполняет генератор до ближайшего yield и возвращает {done: false, value: yieldValue}.

  • Метод generator.return() завершает выполнение генератора.

Т.к. генератор имеет методы next() и return(), то он фактически является итератором.

Общий алгоритм работы генератора:

  • При создании генератора код находится в начале своего выполнения.

  • Вызов next() выполняет генератор до следующего yield.

function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

let generator = generateSequence();

let first = generator.next(); // {"value":1,"done":false}
let second = generator.next(); // {"value":2,"done":false}
let third = generator.next(); // {"value":3,"done":true}

yield expression

Основная цель оператора yield передать значение от генератора наружу и обратно.

Вызов let result = yield value; делает следующее:

  • При вызове next() функция генератор выполняется до yield value;.

  • Возвращает value во внешний код, приостанавливая выполнение генератора.`

    • Если после yield yieldValue; стоит значение, то оно будет значением генератора в момент текущей остановки.

    • Если стоит yield без значения, то на текущем шаге итератор возвращает undefined.

  • Внешний код может обработать значение, и затем вызвать next с аргументом: generator.next(x).

  • Генератор продолжит выполнение, аргумент x будет возвращён как результат yield и записан в result (let result = x).

function* generatorFunction() {
  const result = yield "value";
  // const result = x;
  return result;
}
const generator = generatorFunction();

generator.next(); // {done: false, value: 'value'}
generator.next("outcome"); // {done: true, result: 'outcome'}

yield binds very loosely, so that we don’t have to put its operand in parentheses:

yield a + b + c;
// This is treated as:
yield (a + b + c);
// Not as:
(yield a) + b + c;

Generator algorithm

Алгоритм использования генератора:

  1. При создании генератора код находится в начале своего выполнения.

  2. Первый generator.next(x?) выполнит генератор до первого оператора yield и приостановит свою работу:

    1. Вычисляется значение yield.

    2. Переданное значение x игнорируется.

    3. В результате вызова .next(x?), будет возвращен объект {done: false, value: yieldValue}.

  3. Последующий вызов generator.next(x?):

    • подставит на место текущего yield значение x, если оно было передано.

    • выполнит генератор до следующего yield, вычислит его значение и вернет результат генератору.

  4. Если следующего yield нет, то исполнение доходит до конца функции return returnValue; и возвращается {done: false, value: returnValue}.

Last updated