Yield – дорога в обе стороны

Он не только возвращает результат наружу, но и может передавать значение извне в генератор.

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

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

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

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

Продемонстрируем это на примере:

function* gen() {

// Передать вопрос во внешний код и подождать ответа

let result = yield "2 + 2?";

alert(result);

}

let generator = gen();

let question = generator.next().value; // "2 + 2?"

setTimeout(() => generator.next(4), 2000);

На рисунке ниже прямоугольником изображён генератор, а вокруг него – «внешний код», который с ним взаимодействует:

Yield – дорога в обе стороны - student2.ru

На этой иллюстрации показано то, что происходит в генераторе:

ü Первый вызов generator.next() – всегда без аргумента, он начинает выполнение и возвращает результат первого yield («2+2?»). На этой точке генератор приостанавливает выполнение.

ü Результат yield переходит во внешний код (в question). Внешний код может выполнять любые асинхронные задачи, генератор стоит «на паузе».

ü Когда асинхронные задачи готовы, внешний код вызывает generator.next(4) с аргументом. Выполнение генератора возобновляется, а 4 выходит из присваивания как результат let result = yield ....

Generator.throw

Как мы видели в примерах выше, внешний код может вернуть генератору в качестве результата yield любое значение. Но «вернуть» можно не только результат, но и ошибку!

Для того, чтобы передать в yield ошибку, используется вызов generator.throw(err). При этом на строке с yield возникает исключение. Например:

function* gen() {

try {

// в этой строке возникнет ошибка

let result = yield "Сколько будет 2 + 2?";

}

catch(e) {

alert(e); // выведет ошибку

}

}

let generator = gen();

let question = generator.next().value;

generator.throw(new Error("ответ не найден в моей базе данных"));

Асинхронный код

Одна из основных областей применения генераторов – написание асинхронного кода.

Общий принцип такой:

ü Генератор yield'ит не просто значения, а промисы.

ü Есть специальная «функция-чернорабочий» execute(generator) которая запускает генератор, последовательными вызовами next получает из него промисы – один за другим, и, когда очередной промис выполнится, возвращает его результат в генератор следующим next.

ü Последнее значение генератора (done:true) execute уже обрабатывает как окончательный результат – например, возвращает через промис куда-то ещё, во внешний.

function* doAsyncThings() {

const result1 = doAsyncThing();

const result2 = doAsyncThing(result1);

}

function execute(generator, yieldValue) {

let next = generator.next(yieldValue);

if (next.done) {

return next.value;

}

next.value.then(

result => execute(generator, result),

err => generator.throw(err)

);

}

29. Синтаксис диалекта регулярных выражений, доступный в ES2015. Метасимволы, группировки, обратные ссылки, квантификаторы, символьный класс и выбор, позиционные проверки.

Регулярные выражения (Regular Expressions, RegEx, RegExp) – отдельный язык (может быть использован в редакторах и других языках программирования), который позволяет описать некий текстовый шаблон.

Perl Compatible Regular Expressions (PCRE) - библиотека, реализующая работу регулярных выражений в стиле Perl (с некоторыми отличиями).

Регулярное выражение состоит из двух типов символов. Специальные символы (вроде * в файловых шаблонах) называются метасимволами. Все остальные символы, т. е. обычный текст, называются литералами.

Позиционная проверка (привязка идет к позиции, а не к символу)

^ - начало строки, $ - конец строки (^$ — пустая строка)

/cat/ = «cat» и «vocation»

/^cat/ = «cats», /cat$/ = «scat»

[] – символьный класс

В квадратных скобках происходит перечисление символов, которые могут встретиться (совпасть может только один символ). Позиционные метасимволы, как метасимволы, в символьном классе не работают.

/gr[ea]y/

/<[Hh][123456]>/ — заголовок HTML

Метасимвол символьного класса ‘-’ (дефис) обозначает интервал символов.

[0-9] [a-z] [а-яё]

/<[Hh][1-6]>/

Инвертированные символьные классы

Например, /[^1-6]/ совпадает с символом, не принадлежащим интервалу от 1 до 6. Префикс ^ в каком-то смысле «инвертирует» список, вместо того чтобы перечислять символы, принадлежащие классу, вы перечисляете символы, не входящие в него.

| - конструкция выбора

/gr(a|e)y/

Границы слов (\b, \<, \>)

/\bcat\b/

/\<cat\>/

Квантификаторы

жадный (по умолчанию) – захватывает все, что можно захватить, а потом отпускает

не жадный (квантификатор?) – захватывает по-минимуму

захватывающий (квантификатор+) – не отпускает то, что уже захватил

? - один или ноль совпадений

+ - один или несколько совпадений

* - ноль или несколько совпадений

{min,max} – от min до max совпадений

/colou?r/ (применится к символу ”u”, то есть он может встретиться 0 или один раз)

() - сохраняющая группировка (“\1” - обратная ссылка)

В программах с поддержкой обратных ссылок круглые скобки «запоминают» текст, совпавший с находящимся в них подвыражением, а специальный метасимвол «\1» представляет этот текст (каким бы он ни был на тот момент) в оставшейся части регулярного выражения.

/\b([A-Za-z]+)\s+(\1\s+)*\1\b/ - поиск повторяющихся слов

(?:) – несохраняющая группировка

(?>) - атомарная группировка (совпадение или включено полностью, или полностью исключено)

Метасимволы регулярных выражений:

. – [^\n\r]

\t - символ табуляции

\n - символ новой строки

\r - символ возврата каретки

\s – множество интервальных символов

\S – инвертированное множество интервальных символов

\w - [a-zA-Z0-9_]

\W - [^a-zA-Z0-9_]

\d - [0-9]

\D - [^0-9]

Ключи (флаги):

/i — игнорирование регистра

/g — глобальный поиск

/x — свободное форматирование (любой интервальный символ игнорируется)

/s — рассматривать все, как сплошную строку

/m — разбивает текст на логические строки

/y – начинать поиск с позиции предыдущего совпадения

PCRE:

(?P=name) – ссылка на именованное сохранение

(?P<name>..) – именованное сохранение

\A и \Z – начало и конец всего текста

\Q..\E – литеральный режим (метасимволы внутри игнорируются)

\pL – литеральный символ юникода

\pN – числовой символ юникода

\pZ – интервальный символ юникода

(?i:…) и (?-i:…) – применение или отключение ключа к фрагменту

Позиционная проверка

Опережающая: позитивная (?=…) и негативная (?!...) – позиция, после которой идет или не идет данная последовательность

Ретроспективная: позитивная (?<=…) и негативная (?<!...) – позиция, перед которой идет или не идет данная последовательность

Раскрутка цикла

начало норм* (спец норм*)* конец

Поиск текста в ограничителях:

"(\\.|[^\\"])*"

"[^\\"]*(\\.[^\\"]*)*"

Наши рекомендации