在发送回调函数上的数据之前,如何等待直到完成全部请求并完成了promise?

时间:2019-02-27 09:36:53

标签: javascript promise async-await es6-promise

我有一个包含5个项目的对象,每个项目都会发送一次HTTP请求3次。 我将其保存在

         var promise 
         var promise1 
         var promise2

最后,我将使用以下方式解决(尝试)诺言

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

然后将数据发送到回调函数。

我正在使用array.map()在该阵列上执行任务,所有请求和Promise.all都在其中发生。

在发送回调函数中的数据之前,如何等待直到完成全部请求并完成了promise?

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 :(得分:1)

该代码存在几个问题:

    如果
  1. requestJahrStatistic如果通过调用回调报告其结果,则不应为async

  2. 您可以在几个地方使用此模式:

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

    这毫无用处(除非...请参阅#5),并且可以完全删除。

  3. 没有理由将map回调设为async,因为您没有在其中使用await

  4. 您正在重复将sendHTTPRequest包装在承诺中的逻辑,并且无法处理其中的错误。不要重复自己,为此做一个函数。

  5. HTTP请求似乎使用了connection.statistic_idconnection.reporting_period。他们不应该这样,那是远距离的诡异动作。 :-)但是,如果它们是,则可以并行执行,因为您必须等待使用给定的statistic_idreporting_period完成的请求,然后才能开始下一个。

  6. 您没有处理错误。

如果我假设HTTP请求使用connection.reporting_period,则意味着它们不能重叠,因此这两个请求不能并行进行,因此不能使用Promise.all。您将需要以下内容:

如果HTTP请求未使用connection.reporting_period ,则可以全部并行进行:

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
    });
}

或者类似的东西。