Перейти от обратных вызовов к асинхронному ожиданию в Node

1656590770 perejti ot obratnyh vyzovov k asinhronnomu ozhidaniyu v node

от Nitish Phanse

1*ImJyPIRNLiLXjGSfJQl_dA

Недавно я снова получил шанс поработать с Node. Будучи большим поклонником обещаний, я никогда не пробовал async await. Почему? Потому что обещания сработали для меня вот почему.

Конечно, обещает работать нормально для простых контролеров. Пара запросов в базу данных и обработки ошибок, тогда обещания могут быть неприятными. Да, даже если вы их цепочите. Что, если какая-нибудь решенная ценность в вашей второй цепочке обещаний понадобится в вашем четвертом обещании? Но опять же, я обычно пробовал себе путь (определите переменную let в верхней части области действия функции и переназначьте ее, а затем используйте ее).

Определение случая использования

Я создаю простую спецификацию API, где находится маршрут POST /users . Тело сообщения содержит некоторые сведения о пользователе. Если пользователь существует в базе данных, его значение обновляется, иначе в базе данных создается новая запись.

Для простоты я не использую ORM/базу данных. Я создаю фиктивную модель пользователя и использую setTimeout для имитации вызовов API и запросов к базе данных. Я тоже пользуюсь Math.random() чтобы решить, выдавать ли ошибку для случая обработки ошибок.

Я буду делать эти звонки сначала из-за обратных вызовов, затем из-за обещаний и, наконец, с помощью async/await.

Ладно, время для некоторого кода.

Простой экспресс-сервер

Модель пользователя

Этот код модели пользователя является фиктивным пользовательским объектом, который будет осуществлять имитационные вызовы API. Совершаются два типа звонков: один с обратным вызовом, а другой с обещаниями. Оба эффективно делают тоже самое. Снова я запрограммировал многие вещи здесь ради простоты.

Обратные звонки

Традиционным способом выполнения любого неблокирующего ввода-вывода был обратный вызов, когда любой вызов ввода-вывода имел форму

someAsyncOperation(dataObject, function(error, success) {
  if (error) {    // handle error  } else {    // do something with success  }})

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

Плюсы:

  1. Удобно для отдельных асинхронных операций. Позволяет легко контролировать данные и ошибки.
  2. Должна работать на каждой версии узла и почти на всех пакетах node. Поскольку обратные вызовы являются функциями, им не требуются транспиляторы.

минусы:

  1. Для нескольких вложенных асинхронных операций это создает ад обратного вызова.
  2. Обработка ошибок должна выполняться для каждой операции (нет глобального обработчика исключений)

Обещания

Обещания — это объекты, которые имеют 3 основных состояния — ожидают рассмотрения, решены и отклонены. В зависимости от ответа асинхронного действия обещание либо разрешается, либо отклоняется. Несколько обещаний можно закрепить друг под другом. Для ошибки в любом обещании достаточно одного обработчика catch внизу.

Плюсы:

  1. Позволяет легко объединять асинхронные операции. Все, что возвращается в .then функцию, можно связать в следующую .then функция.
  2. Один обработчик catch внизу перехватит ошибку, если любое из объединенных обещаний генерирует исключение.

минусы:

  1. Большинство библиотек может потребовать обертки promisify вокруг нее, как bluebird, если они не поддерживают обещания из коробки.
  2. Область действия цепной функции изолирована от этой функции. Следовательно, некоторые данные, развязанные во второй цепочке, не могут использоваться в 4-й цепочке, если не объявлена ​​глобальная переменная let.

Асинхронный

Async/await в конце дня все еще является обещанием. Это просто способ написания асинхронного кода синхронно.

Каждая асинхронная функция должна иметь префикс async. Каждое асинхронное действие в нем должно иметь префикс со словом await . Кроме того, каждая асинхронная функция возвращает обещание, которое можно решить дальше.

Плюсы:

  1. ЧИСТЫЙ КОД. Я не могу подчеркнуть этот момент. Ко всем разрешенным битам можно получить доступ в блоке try.
  2. Весь блок можно рассматривать как синхронный код. (хотя это асинхронный характер).
  3. Добавление try, catch в асинхронный код.
  4. Один унифицированный обработчик ошибок в блоке catch.

минусы:

  1. Node 8+ имеет встроенную функцию Async Await. Для старых версий кода на стороне сервера требуется транспиллер babel.
  2. Добавление ключевого слова async не очень интуитивно понятно.
  3. Использование async/await внутри конструктора обещаний является антишаблоном.

4. Опять же, для некоторых библиотек, поддерживающих только обратные вызовы, может потребоваться глобальная библиотека promisify для поддержки async/await

Вывод

В заключение я бы сказал, что мы превратили конкретный вариант использования из одной формы обратных вызовов в обещания для окончательного асинхронного ожидания.

В общем-то, я считаю, что асинхронный код ожидания был действительно чистым и легким для понимания. Поскольку люди хотят изучать Node, они считают асинхронный бит сложной задачей. Кроме того, люди с Java, PHP или даже Python могут легко начать создание приложений на node, не беспокоясь об обратных вызовах/обещаниях.

Надеюсь, эта статья была полезна. Если есть ошибки, пожалуйста, сообщите мне. Буду рад их исправить.

Добавить комментарий

Ваш адрес email не будет опубликован.