Как я могу ждать, пока вся партия запросов не будет выполнена и обещания не будут выполнены, прежде чем я отправлю данные в функцию обратного вызова? - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть объект с 5 элементами, каждый из которых отправит http-запрос 3 раза.Я сохраняю это в

         var promise 
         var promise1 
         var promise2

В конце я решаю (пытаюсь) обещания, используя

Promise.all([promise, promise1, promise2]]

И затем я отправляю данные в функцию обратного вызова.

Я использую array.map () для выполнения своей задачи в этом массиве, все запросы и Promise.all выполняются внутри него.

Как я могу ждать, пока не будет выполнена целая партия запросов, иОбещания решаются до того, как я отправлю данные о функции обратного вызова?

async function requestJahrStatistic(jahreStatistic, callback){
Promise.all(
     jahreStatistic.map(async (item) => {
      var periods = getReportingPeriod(item.period);

      connection.statistic_id = item.statistic_id;

      connection.reporting_period = periods.prevYear;
      var promise = new Promise(function(resolve, reject) {
        sendHTTPRequest(item, function(result) {
          resolve(result);
        });
      });

      connection.reporting_period = periods.actualYear;
      var promise1 = new Promise(function(resolve, reject) {
        sendHTTPRequest(item, function(result) {
          resolve(result);
        });
      });

      connection.reporting_period = periods.nextYear;
      var promise2 = new Promise(function(resolve, reject) {
        sendHTTPRequest(item, function(result) {
          resolve(result);
        });
      });

      Promise.all([promise, promise1, promise2]).then(async resolved => {
        var res = await resolved
        return res
      });
    })
  ).then(async resolved =>{
      var resp = await resolved;
      callback(resp)
  });

}

Это была последняя вещь, которую я пробовал перед написанием вопроса

1 Ответ

0 голосов
/ 27 февраля 2019

Есть несколько проблем с этим кодом:

  1. requestJahrStatistic не должно быть async, если он сообщает о своих результатах путем обратного вызова

  2. Этот шаблон используется в нескольких местах:

    .then(async resolved => {
      var res = await resolved
      return res
    });
    

    Это не имеет смысла (если только ... см. # 5) и может быть полностью удалено.

  3. Нет причины для map обратного вызова async, так как вы не используете await внутри него.

  4. Вы повторяете свою логическую оболочкуsendHTTPRequest в обещании и не может обработать ошибки в нем.Не повторяйте себя, создайте для этого функцию.

  5. Похоже, connection.statistic_id и connection.reporting_period как-то используются HTTP-запросами.Они не должны быть, это жуткое действие на расстоянии.:-) Но если они есть, то нет этого может быть параллельно, так как вам нужно дождаться запроса, используя заданные statistic_id и reporting_period, чтобы завершить следующий.

  6. Вы не обрабатываете ошибки.

Если я предполагаю, что connection.reporting_period используется HTTP-запросами, это означает, что они не могут перекрыватьсятак что ничего из этого не может быть параллельно, и вы не можете использовать Promise.all для него.Вам понадобится что-то вроде:

Если connection.reporting_period не используется HTTP-запросами, все это может быть параллельным:

function sendHTTPRequestP(item) {
    return new Promise((resolve, reject) => {
        sendHTTPRequest(item, result => {
            if (/*an error occurred*/) {
                reject(new Error(/*...*/));
            } else {
                resolve(result);
            }
        });
    })
}

// Completely serial because of spooky action at a distance with
// `connection.statistic_id` and `connection.reporting_period`
function requestJahrStatistic(jahreStatistic, callback) {
    Promise.resolve(async () => {
        const results = [];
        for (const item of jahreStatistic) {
            const periods = getReportingPeriod(item.period);
            connection.statistic_id = item.statistic_id;

            connection.reporting_period = periods.prevYear;
            const result1 = await sendHTTPRequestP(item);

            connection.reporting_period = periods.actualYear;
            const result2 = await sendHTTPRequestP(item);

            connection.reporting_period = periods.nextYear;
            const result3 = await sendHTTPRequestP(item);

            results.push([result1, result2, result3]);
        }
        return results;
    })
    .then(callback)
    .catch(error => {
        // Handle/report error, call `callback` with the appropriate error flag
    });
}

Или что-то подобноеэти строки.Обратите внимание, что callback получит массив массивов.Внешний массив будет иметь столько записей, сколько и jahreStatistic;каждая из этих записей будет массивом результатов трех HTTP-вызовов.

Если вы можете что-то изменить, чтобы каждая операция принимала аргументы, а не пугающее действие на расстоянии (я вижу, что sendHTTPRequest уже имеет item так можно предположительно получить statistic_id из него, поэтому нам просто нужно передать period), вы можете сделать вещи параллельными:

function sendHTTPRequestP(item, reporting_period) {
    return new Promise((resolve, reject) => {
        sendHTTPRequest(item, reporting_period, result => {
            if (/*an error occurred*/) {
                reject(new Error(/*...*/));
            } else {
                resolve(result);
            }
        });
    })
}

function requestJahrStatistic(jahreStatistic, callback){
    Promise.all(
        jahreStatistic.map((item) => {
            const periods = getReportingPeriod(item.period);
            return Promise.all([
                sendHTTPRequestP(item, periods.prevYear),
                sendHTTPRequestP(item, periods.actualYear),
                sendHTTPRequestP(item, periods.nextYear)
            ]);
        })
    )
    .then(callback)
    .catch(error => {
        // Handle/report error, call `callback` with the appropriate error flag
    });
}

или что-то в этом роде.

...