Аналог паттерна Step и вложенность асинхронных вызовов

в 12:05, , рубрики: javascript, nodejs, метки: ,

При реализации модели для манипуляции с данными в MongoDB, я пришел к выводу, что нужно как то избежать проблем с вложенностью асинхронных вызовов. Я не знал о существовании Step для Node.js и решил создать свой велосипед. Чем и хотел бы с Вами поделиться, уважаемые Хабро пользователи.

Вступление

Для того чтобы решить проблему вызовов и дальнейшей передачи информации, следующему в очереди вызову, родился модуль AQueue (реализация последовательной очереди асинхронных вызовов). В реализации данного модуля, лежит принцип, применяемый в реализации промежуточного слоя роутинга в Express.js (к примеру для проверки возможности доступа к той или иной view). Данный механизм реализован посредством вызова callback функции под названием next() с передачей ей необходимых параметров.

И так приступим!

Реализация

Для организации очереди был выбран массив в который заносятся функции, в той последовательности, в которой они будут вызваны.

  • Функция AddTo — производит добавление в очередь, очередной функции.
  • Функция next — позволяет вызывать следующую по порядку функцию.
  • Функция completed — вызывается при успешном завершении, либо когда параметр err не null
  • Функция run — производит запуск механизма вызовов в порядке очереди.
  • Свойство q — используется для хранения функций в массиве.
  • Свойство cb — используется для хранения функции завершения очереди вызовов.
  1. function AQueue(){
  2.     var that = this;
  3.     that.q = [];
  4.     that.cb = null;
  5.  
  6.     that.addTo = function(f){
  7.         that.q.push(f);        
  8.         return that;
  9.     };
  10.  
  11.     that.next = function(err, data){
  12.         if(that.q.length>0){
  13.             var f = that.q.shift();
  14.             if(err){
  15.                 that.q = [];
  16.                 that.cb(err, data);
  17.             }else{
  18.                 f(that.next, err, data);                        
  19.             }
  20.         }else{
  21.             that.cb(err, data);
  22.         }
  23.     };
  24.  
  25.     that.completed = function(cb){
  26.         that.cb = cb;
  27.         return that;
  28.     };
  29.  
  30.     that.run = function(){
  31.        return that.next(null, null);
  32.     };
  33. }
  34.  
  35. exports.AQueue = AQueue;
  36.  
Использование

Ниже представлен пример использования модуля  AQueue.

  1. var AQueue = reqiure('aqueue').AQueue;
  2.  
  3. var aq = new AQueue();
  4.     aq.addTo(function(next, err, data){    
  5.          // производим необходимые действия
  6.          next(err, data);
  7.     }).addTo(function(next, err, data){
  8.      //производим дополнительные действия
  9.         // можно комбинировать данные, оборачивая в объект
  10.      next(err, {data: data, checked :  true});  
  11.     }).completed(function(err,data){
  12.         //выполнение финальных действий.
  13.     }).run();

Автор: CyberLight

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js