等待foreach循环以在javascript中执行内部异步代码

时间:2020-05-08 19:59:58

标签: javascript loops foreach promise

我写了下面的函数

function test() {
apiCall.ajaxCallWithReturnData(obj, 'GET', 'url')
    .then(res => {
        var metrics

        metrics = res.Data.map((d) => { //filling metrics array
            return {
                MetricID: d.MetricID,
                Metric: d.Metric
            }
        })
        weeklyChartdata(null, 'Overall') //call method for default metric
            .then(result => {
                console.log('start')

            })
            .then(() => {
                //console.log(scors)

                metrics.forEach(function (m, i) {//Loop each metric
                    console.log('loop' + i)

                    weeklyChartdata(m.MetricID, m.Metric)
                        .then(result => {
                            console.log('loop' + i + 'result', result.scors)
                        })

                })//Loop each metric                     

            })
            .then(() => {
                console.log('done')
            })

    })

}

使用上述代码,我希望得到类似于波纹管的结果

start

loop0
loop 0 result 
loop1
loop 1 result 
loop2
loop 2 result 

done

但是结果却像波纹管命令那样生成

start
loop0
loop1
loop2
done
loop 0 result 
loop 1 result 
loop 2 result 

我了解 metrics.forEach 会不断发展,而不是等待其余代码的执行。 请建议我如何处理这种情况,以等待循环执行所有代码。

2 个答案:

答案 0 :(得分:0)

我相信您正在寻找Promise.all()

metrics.forEach(function (m, i) {//Loop each metric
                console.log('loop' + i)

                weeklyChartdata(m.MetricID, m.Metric)
                    .then(result => {
                        console.log('loop' + i + 'result', result.scors)
                    })

            })//Loop each metric      

成为(未经测试)

        const promises = [];
        metrics.forEach((m, i) => {//Loop each metric
                console.log('loop' + i)

           promises.push(weeklyChartdata(m.MetricID, m.Metric)
                    .then(result => {
                        console.log('loop' + i + 'result', result.scors)
                        return result;
                    })
           )  

        })//Loop each metric
        Promise.all(promises).then((results) => {
          console.log(results);
        });

希望这会有所帮助(请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all)。

注意:console.logs的顺序并不重要,它与您在Promis.all承诺中的结果有关

答案 1 :(得分:0)

Promise.all是实现此目标的完美方法,用户3791775回答。我正在提出另一种方式。

forEach不适用于异步功能。您可以改用for-of loop。因此,您的metric.forEach应该类似于下面的代码(未经测试)

let i=0;
for (const m of metrics){
  console.log('loop' + i)
  weeklyChartdata(m.metricID, m.metric)
  .then(result => {
      console.log('loop' + i + 'result', result.scors)
  })
  i++;
}