异步等待代码与forEach的运行方式不同

时间:2019-05-09 11:15:16

标签: javascript node.js typescript async-await

我有这段代码,当我运行时,它将依次运行“一”和“二”。

因此下面的代码可以正常工作。

(async () => {

  await runit('one').then(res => {
    console.info(res);
  });

  await runit('two').then(res => {
    console.info(res);
  });

})();

现在,我想做同样的事情,但是要循环执行,所以我做到了:

const arr = ['one', 'two'];
  arr.forEach(element => {
    (async () => {
      await runit(element).then(res => {
      console.info(res);
    });
  })();
});

尽管似乎是相同的代码,但不再按照顶部的代码顺序运行。

我该如何解决?

3 个答案:

答案 0 :(得分:2)

您可以使用promise.all函数来实现相同的目的,如下所示。

const arr = ['one', 'two'];
const promises = [];
  arr.forEach(element => {
      promises.push(runit(element));
  });

Promise.all(promises).then(results => {
    console.log(results)//you will get results here.
});

答案 1 :(得分:2)

它不会等待,因为您执行的功能是异步的,您实际上是在告诉它不要等待。要解决它,您可以简化循环:

for (let i = 0; i < arr.length; i++) {
  const item = arr[i];
  await runit(item).then(res => {
    console.info(res);
  });
}

或者您可以使用map和Promise.all:

const promises = arr.map(item => runit(item)));
const values = Promise.all(promises);
values.forEach(res => console.info(res))

首选后者。

答案 2 :(得分:1)

避免将 this.clusterLayer = L.markerClusterGroup({ spiderfyOnMaxZoom: false, showCoverageOnHover: false, zoomToBoundsOnClick: false, maxClusterRadius: 20, animate: true, iconCreateFunction: () => { return this.aggregateIcon; } }); this.clusterLayer.on('clusterclick', (clusterEvent: any) => { clusterEvent.sourceTarget .bindPopup((e) => { return this.createAggregatePopup(clusterEvent); }, { className: 'custom-popup aggregate', closeButton: false}) .openPopup(); }); this.map.addLayer(this.clusterLayer); this.map.on('popupopen', (e: any) => { //Remove marker from clusterLayer and add it to the map e.popup._source.addTo(this.map); this.clusterLayer.removeLayer(e.popup._source); }); this.map.on('popupclose', (e: any) => { //Re-add the marker to the cluster layer this.map.removeLayer(e.popup._source); this.clusterLayer.addLayer(e.popup._source); }); forEach一起使用。它不会正常工作。

await会忽略它所使用的回调函数的所有结果。如果您将其传递给forEach函数-或其他任何返回诺言的函数-所有返回的诺言将不予处理。

改为使用本机for循环。 要匹配一次只运行一项的非循环代码,请执行以下操作:

async

这与for (const element of ['one', 'two']) { console.log(await runit(element)); } 的其他答案有很大不同。 Promise.all等待多个诺言的批发完成,这意味着事情已经并行运行。

要并行运行,请执行以下操作:

Promise.all