Как ждать нескольких обратных вызовов в Node js - PullRequest
0 голосов
/ 12 марта 2019

Я пытаюсь дождаться нескольких обратных вызовов, но не могу придумать, как сделать это красиво.

Мой код:

module.exports.getFilledOnlineFormsOfArray = (formIDs, callback) => {
let forms = [];
for (let i = 0; i < formIDs.length; i++) {
    this.getFilledOnlineFormByID(formIDs[i], (err, filledForm) => {
        if (err) callback(err);
        else forms.push(filledForm);
    });
}
callback(null, forms);
};

Как мне позвонить callback(null, forms) только после разрешения каждого обратного вызова getFilledOnlineFormByID (IE (err, filledForm))?

Я придумал решение написать:

module.exports.getFilledOnlineFormsOfArray = (formIDs, callback) => {
    let forms = [];
    let count = formIDs.length;
    for (let i = 0; i < formIDs.length; i++) {
        this.getFilledOnlineFormByID(formIDs[i], (err, filledForm) => {
            if (err) callback(err);
            else forms.push(filledForm);
            count--;
            if (count === 0)
                callback(null, forms);
        });
    }
};

Но плохо так кодировать это. Я уверен, что есть более элегантное решение этой проблемы. Я искал ответы в Интернете, но все, что я нашел, это как преобразовать его в асинхронные функции, и я не могу сделать это в моем проекте прямо сейчас.

РЕДАКТИРОВАТЬ: Я пытался использовать Promise.all так:

module.exports.getFilledOnlineFormsOfArray = (formIDs, callback) => {
    let forms = [];
    let async = [];
    for (let i = 0; i < formIDs.length; i++) {
        async.push(this.getFilledOnlineFormByID(formIDs[i], (err, filledForm) => {
        if (err) callback(err);
        else forms.push(filledForm);
       }));
    }
    Promise.all(async).then(callback(null, forms));
};

но это не сработало.

Ответы [ 2 ]

1 голос
/ 12 марта 2019

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

const util = require('util');

module.exports.getFilledOnlineFormsOfArray = (formIDs, callback) => {
    // make a promisified version of the method
    if (!this.getFilledOnlineFormByIDPromise) {
        this.getFilledOnlineFormByIDPromise = util.promisify(this.getFilledOnlineFormByID);
    }

    // use Promise.all() to track when all the promises have completed
    Promise.all(formIDs.map(id => {
        return this.getFilledOnlineFormByIDPromise(id);
    })).then(results => {
        callback(null, results);
    }).catch(err => {
        callback(err);
    });    
};

Лично я бы изменилинтерфейс getFilledOnlineFormsOfArray() для простого возврата обещания и прекращения использования обратных вызовов для управления асинхронными операциями.Вы также можете исправить реализацию this.getFilledOnlineFormByID() в источнике, а не обещать ее здесь.Но я предложил кое-что, что будет работать с кодом, который вы показали.

Примечание. При использовании обещаний лучше всего обещать операции более низкого уровня, а затем реализовать весь поток управления и обработку ошибок, используяобещания.Это также, как правило, намного проще (поскольку обещания особенно хороши для распространения ошибок, а обратные вызовы - нет).Смешивание обратных вызовов и обещаний на более высоких уровнях вашего кода может очень быстро запутаться.

0 голосов
/ 12 марта 2019

Мы можем использовать async.parallel для запуска нескольких задач.

const async = require('async');

 module.exports.getFilledOnlineFormsOfArray = (formIDs, callback) => {
  let taskList = [];
  let forms = [];
  for (let i = 0; i < formIDs.length; i++) {
    taskList.push(function(cb){
      this.getFilledOnlineFormByID(formIDs[i], (err, filledForm) => {
          forms.push(filledForm);
          cb(err, filledForm)
       });
    });
  }
  async.parallel(taskList, function (errs, results) {
    if (errs) {
        console.log(errs);
    }
    console.log('Task list done.', results);
  })
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...