> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/e-controls/e3-generators/03-generator-execution.md).

# 03. Generator Execution

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

1. Описании функции генератора `function* generatorFunction()`;
2. Получение объекта генератора `generator`.

```javascript
// 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`.

```javascript
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`).

```javascript
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:

```javascript
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}`.
