ALEXPTS
WEB DEVELOPER
PHP, NodeJS, JavaScript, etc.
Главная Приколы Стена
Cкилы: Web Php NodeJs Tests Storages

Синхронный flow в асинхронном nodejs

#Dev #NodeJs

На nodejs пишу порядка 2 лет. Начиналось все с простеньких скриптов без использования какого-то фреймворка. За основу брался модуль http, все описывалось руками.

Далее начал работать с широко известным в мире nodejs фреймворком express. В дальнейшем спортивный интерес привел меня к фреймворку koa, который изменил мое отношение к разработке на nodejs в лучшую сторону и заставил полюбить мир nodejs.

Callback ад

В виду асинхронной природы nodejs, как правило, функция принимает последним параметром так называемую функцию обратного вызова (callback function). Когда асинхронная функция будет выполнена, то она вернет управление функции обратного вызова, передав ей результат выполнения или ошибку. Таким образом спроектированы почти все методы ядра nodejs по сей день.

Как правило, в приложении множество вызовов, каждый последующий вызов зависит от результата предыдущего. Таким образом, функции обратного вызова вкладываются друг в друга (если это анонимные функции), и получается так называемый callback ад. Если это ссылки на функции, то управление переходит в них, код становится не вложенным, а размазывается по приложению, и прочитать такой код становится тоже достаточно сложно.

    // ...
        AsyncFunction(..., function(){
            ...
        });
    });
});

Цепочка обещаний - Promise

Далее на смену функции обратного вызова пришел объект обещаний Promise, который стал глотком свежего воздуха. Благодаря цепочке обещаний стало возможно писать код с меньшим числом вложений. Теперь работа с асинхронными вызовами стала выглядеть так:

fetch(...)
.then(function(result){...})
.then((result) => {...})
.then((result) => {...});

Результат асинхронного вызова передается в следующий блок then, который представляет собой функцию. При этом эта функция может вернуть какой-то конкретный результат или результат вызова другой функции, в том числе и асинхронной, который будет представлен Promise объектом. В этом случае это обычно называют цепочкой промисов.

Генераторы + Promise => Coroutine

Далее я познакомился с koa js и с генераторами. Благодаря корутинам в koa js я в корне изменил свое отношение к разработке на nodejs и, до появления php 7 с более строгой типизацией, даже всерьез задумался о полном переходе в мир nodejs.

Coroutine позволили писать асинхронный код в синхронном flow, как-будто бы я работаю с синхронными методами. Выглядит это так:

let data = yield fetch(...);

Генератор выкидывает результат вызова асинхронной функции в виде промиса, и управление выходит из этой функции. Управление возвращается назад в функцию, когда промис зарезолвится. Результат резолва промиса присваивается переменной data, будто бы функция fetch является синхронной.

Это позволило писать простой и не запутанный для чтения код. Также такой код стало проще тестировать и поддерживать.

Async / Await

Будущая реализация для синхронного flow - async / await. В настоящий момент нет нативной поддержки, но многие уже переводят свои библиотеки на async / await и применяют babel для запуска такого кода.

Заключение

Мир nodejs очень динамично развивается. От сложного подхода с callback адом можно прийти к синхронному flow, который будет очень привычным, если ранее вы работали с языком, где все методы синхронные.