The words you are searching are inside this book. To get more targeted content, please make full-text search by clicking here.

Браун Э. - Изучаем JavaScript. Руководство по созданию современных веб-сайтов - 2017

Discover the best professional documents and content resources in AnyFlip Document Base.
Search
Published by koblay.yuriy, 2020-07-17 10:07:58

Браун Э. - Изучаем JavaScript. Руководство по созданию современных веб-сайтов - 2017

Браун Э. - Изучаем JavaScript. Руководство по созданию современных веб-сайтов - 2017

Если вы уже говорите "Ого." функция, которая возвращает функцию, которая
возвращает обязательство, которое вызывает функцию, которая возвращает обя­
зательство... У меня уже голова кружится!': я могу вас понять: добавление периода
в возвращающую обязательство функцию не является тривиальной задачей и требу­
ет напряжения всех извилин. Полное понимание этой функции является упражнени-
ем для "продвинутого" читателя. Однако использовать эту функцию весьма просто:
мы можем добавить период к любой функции, которая возвращает обязательство.
Скажем, наша самая медленная ракета достигает орбиты через 1 О секунд (разве не
прекрасны ракетные технологии будущего?). Таким образом, мы устанавливаем пе­
риод на 1 1 секунд.

с . go ( )
. then ( addTimeout ( launch, 4 * 1 0 00 ) )
. then ( function (msg) {
console . log (msg) ;
})
. ca t ch ( funct ion ( er r ) (
console . error ( "Xьюcтoн, у нас проблемы: " + err . me s sage ) ;

});

Теперь наша цепь обязательств всегда будет завершаться, даже когда функция
launch ведет себя плохо.

Генераторы

Как уже обсуждалось в главе 1 2, генераторы обеспечивают двухстороннюю связь
между функцией и ее вызывающей стороной. Генераторы синхронны по своей при­
роде, но, будучи объединены с обязательствами, обеспечивают мощную технологию
для управления асинхронным кодом в JavaScript.

Давайте припомним главную сложность асинхронного кода: его труднее писать,
чем синхронный код. Когда мы решаем задачу, наш ум стремится свести ее к син­
хронному виду: этап 1, этап 2, этап 3 и т.д. Однако при этом подходе могут быть про­
блемы производительности, которых нет при асинхронном подходе. Разве не было

246 Глава 1 4. Асинхронное программирование

бы хорошо иметь преимущества производительности асинхронных технологий без
дополнительных концептуальных трудностей? Вот где могут пригодиться генерато­
ры.

Рассмотрим использованный ранее пример "проклятья обратных вызовов": чте­
ние трех файлов, задержка на одну минуту и последующая запись содержимого пер­
вых трех файлов одного за другим в четвертый файл. Наш человеческий разум хо­
тел бы написать это в виде примерно такого псевдокода.

dataA читаем содержимое файла ' a . txt '
dataB = читаем содержимое файла ' b . txt '

dataC = читаем содержимое файла ' c . txt '

Ждем 6 0 секунд
Записываем dataA + dataB + dataC в файл ' d . txt '

Генераторы позволяют нам писать код, который выглядит очень похоже на этот...
однако необходимые функциональные возможности не появятся как из коробки:
сначала придется проделать небольшую работу.

Первое, что необходимо, - это способ превратить функцию обратного вызова
с первым аргументом для передачи ошибки Node в обязательство. Мы инкапсулиру­
ем это в функцию nfcall (Node function call - вызов функции Node).

function nfcall ( f , . . . args ) {
return new Promise ( funct ion ( re s o lve , rej ect ) {
f . cal l ( nu l l , . . . args , function ( err, . . . args )
i f ( err) return rej ect ( err) ;
resolve ( args . length<2 ? args [ O ] : args ) ;
});
}) ;

Эта функция названа в честь метода nfca l l из библиотеки обяза­
тельств Q (и реализована на его основе). Если вам необходимы эти
функциональные возможности, лучше всего воспользуйтесь библио­
текой Q. Она включает не только этот метод, но и много других по-
лезных методов, также связанных с обязательствами. Я же представ­
ляю реализацию nfcall для демонстрации того, что никакого "вол­
шебства" здесь нет.

Теперь мы можем преобразовать любой метод, написанный в стиле Node, так,
чтобы он получал обратный вызов для обязательства. Нам также понадобится функ­
ция setTimeout, которая получает обратный вызов... но поскольку она появилась
задолго до Node, она не соответствует соглашению о передаче ошибок функциям
обратного вызова. Поэтому необходимо создать новую функцию ptimeout (promise
timeout - период обязательства).

Генераторы 247












Click to View FlipBook Version