При реализации модели для манипуляции с данными в MongoDB, я пришел к выводу, что нужно как то избежать проблем с вложенностью асинхронных вызовов. Я не знал о существовании Step для Node.js и решил создать свой велосипед. Чем и хотел бы с Вами поделиться, уважаемые Хабро пользователи.
Вступление
Для того чтобы решить проблему вызовов и дальнейшей передачи информации, следующему в очереди вызову, родился модуль AQueue (реализация последовательной очереди асинхронных вызовов). В реализации данного модуля, лежит принцип, применяемый в реализации промежуточного слоя роутинга в Express.js (к примеру для проверки возможности доступа к той или иной view). Данный механизм реализован посредством вызова callback функции под названием next() с передачей ей необходимых параметров.
И так приступим!
Реализация
Для организации очереди был выбран массив в который заносятся функции, в той последовательности, в которой они будут вызваны.
- Функция AddTo — производит добавление в очередь, очередной функции.
- Функция next — позволяет вызывать следующую по порядку функцию.
- Функция completed — вызывается при успешном завершении, либо когда параметр err не null
- Функция run — производит запуск механизма вызовов в порядке очереди.
- Свойство q — используется для хранения функций в массиве.
- Свойство cb — используется для хранения функции завершения очереди вызовов.
- function AQueue(){
- var that = this;
- that.q = [];
- that.cb = null;
- that.addTo = function(f){
- that.q.push(f);
- return that;
- };
- that.next = function(err, data){
- if(that.q.length>0){
- var f = that.q.shift();
- if(err){
- that.q = [];
- that.cb(err, data);
- }else{
- f(that.next, err, data);
- }
- }else{
- that.cb(err, data);
- }
- };
- that.completed = function(cb){
- that.cb = cb;
- return that;
- };
- that.run = function(){
- return that.next(null, null);
- };
- }
- exports.AQueue = AQueue;
Использование
Ниже представлен пример использования модуля AQueue.
- var AQueue = reqiure('aqueue').AQueue;
- var aq = new AQueue();
- aq.addTo(function(next, err, data){
- // производим необходимые действия
- next(err, data);
- }).addTo(function(next, err, data){
- //производим дополнительные действия
- // можно комбинировать данные, оборачивая в объект
- next(err, {data: data, checked : true});
- }).completed(function(err,data){
- //выполнение финальных действий.
- }).run();
Автор: CyberLight