Page 245 - Браун Э. - Изучаем JavaScript. Руководство по созданию современных веб-сайтов - 2017
P. 245
function ptimeout (delay) {
return new Promise ( f unction ( r e s olve , rej ect ) {
setTimeout { r esolve , delay) ;
} ) ;
Следующее, что нам понадобится, - это пускатель генератора (generator runner).
Не забывайте, что генераторы не являются по своей природе асинхронными. Но по
скольку они позволяют функциям общаться с вызывающей стороной, мы можем
создать функцию, которая будет управлять этой связью и знать, как обрабатывать
асинхронные вызовы. Поэтому создадим функцию grun (generator run - пуск гене
ратора).
function grun ( g ) {
const i t = g ( ) ;
( f unction iterate (v l )
a
const х = it . n ext ( v al ) ;
if ( ! . don ) {
х
e
i
i f ( x . v a l ue instanceof Prom s e ) {
x . v a l ue . t hen ( iterate ) . c atch ( e rr => i t . throw ( e r ) ) ;
r
else {
setTimeout ( i terate , О , x . v alu ) ;
e
} ) ( ) ;
Данная функция grun основана на функции runGenerator, представ
ленной Кайлом Симпсоном (Kyle Simpson) в его превосходной серии
статей о генераторах. Я настоятельно рекомендую прочитать эти
статьи как дополнение к данному тексту.
Это очень скромный рекурсивный пускатель генератора. Вы передаете ему функ
цию генератора, и он запускает его. Как уже было сказано в главе 6, генераторы, кото
рые вызывают оператор yield, будут делать паузу, пока не будет вызван метод next
его итератора. Данная функция делает это рекурсивно. Если итератор возвращает
обязательство, она ожидает выполнения обязательства перед возобновлением итера
тора. С другой стороны, если итератор возвращает простое значение, она немедлен
но возобновляет итерацию. Вы можете задаться вопросом "Почему происходит вызов
setTirneout вместо обычного непосредственного вызова i terate?" Причина в том,
что мы получим более эффективный код при отказе от синхронной рекурсии (асин
хронная рекурсия позволяет движку JavaScript освобождать ресурсы куда быстрее).
Вы можете подумать "Как много суеты!" и "Это называется упрощает жизнь?" Од
нако сложная часть завершена. Функция nfcall позволяет увязать прошлое (функции
248 Глава 1 4 . Асинхронное программирование

