5. Только AJAX и setTimeout?
• Работа с файлами (FileAPI, fs)
• Анимации (requestAnimationFrame, тайминги)
• WebWorkers
• События DOM
• «Тяжелые» циклы
• И так далее…
Название созвучно с лозунгом одного очень известного политика в одной очень известной стране. Мы его сегодня еще увидим.
Кто пишет асинхронный код на JS?
Нечто подобное вы наверняка видели в начале своей карьеры или на собеседованиях в качестве одного из первых вопросов.
То чувство, когда начинаешь что-то подозревать…
Что такое асинхронность?
Мы не будем рассматривать асинхронность на примере этой схемы.
Асинхронность для меня, как для человека, который пишет и читает код – это …
Какие функции могут быть асинхронными?
Рассмотрим абстрактную задачу.
Я записал вызовы функций в той последовательности, в которой по-моему мнению коду стоило бы выполняться: получить список твитов, обработать список авторов и вывести его в консоль. В некоторых других языках это бы вполне работало.
Но в JS – нет.
Ну теперь уже точно не подозреваешь, а откровенно в шоке…
Решение в лоб: передать некоторые функции, которые выполнятся только после завершения асинхронного действия. Функции обратного вызова.
Этот код весьма нелегко читать и поддерживать.
Добавление дополнительного вызова метода «углубляет» нас в этой иерархии.
Есть еще одно НО…
Т.к. коллбек выполняется в другом контексте, можно допустить ошибку при использовании `this`.
Поверьте, в эпоху до стрелочных функций это была очень распространенная ошибка. С лечением типа `var self = this` и bind(this), но не все и сейчас знают про bind))
Давайте внимательно посмотрим на каноническую пирамиду коллбеков в вакууме.
Здесь есть всё: и консоль логи, и форычи, и bind this. Вложенность вызовов все углубляется и углубляется.
Подобный код до сих пор можно найти в плагинах для того же ExpressJS v4.
Забыл предупредить что вас снимает скрытая камера!
Кто узнал себя?
Различные библиотеки.
Главная идея: вызов асинхронной функции возвращает нам некий объект, для которого мы можем описать поведение на изменение статуса (успешно/неудачно).
Комикс Mariko Kosaka
В комиксе автор описывает промис, как брелок, который выдает мне повар…
А брелок в свою очередь оповестит меня, когда стоит подойти на стойку выдачи заказа, чтобы получить или нет бургер.
Некоторое подобие одноразового медиатора.
Полезные ссылки
Я переписал код на промисы.
Промис можно возвращать в функцию высшего порядка.
Последовательность инструкций достаточно легко читать.
Сложность: новички (и не только) могут запутаться в цепочках then-catch.
Promise.race()
Возвращается итератор.
Вызываем next => объект-итерация.
Фактически, есть возможность запаузить функцию. Т.е. передать управление функции высшего порядка, не теряя состояние текущей.
Споры: звездочка в имени функции.
Как запускать?
Можно написать свою обертку, которая будет вызывать итератор, проверять его состояние done true/false, исполнять код далее или нет.
Библиотек CO.
CO сам создает итератор, вызывает next() нужное кол-во раз и т.д.
Такой подход используется в KoaJS v.1
В целом, у меня получилось написать последовательность инструкций, которая выполняется в этом порядке, этот код гораздо легче читать и писать.