【问题标题】:Wait for multiple for-each statements to be finished等待多个 for-each 语句完成
【发布时间】:2019-03-26 18:17:40
【问题描述】:

我有一个集群数组,其中每个集群都包含一组特征。我使用两个 forEach 语句来遍历集群和特征,以便将每个特征存储在我的“结果”数组中。

我需要进一步处理我的“结果”数组。但是当我询问数组的长度时,它说长度为 0,尽管我可以在控制台中看到其中有一些特性。我需要找到一种仅在 forEach 循环完成时处理“结果”数组的方法。

我已经读到这个问题是由 JavaScript 中的异步数据处理引起的。我已经尝试注册一个 Promise,但我无法让它工作,因为在示例中总是使用一个 forEach 循环,但我有两个 forEach 循环。

这是我的代码:

var result = [];

clusters.forEach((cluster) => {
  getFeatures(cluster_id, (features) => {
  features.forEach((feature) => {
    result.push(feature);
  });
  });
});

//do something with result array
console.log("resulting features array length: " + result.length); //results in 0

【问题讨论】:

  • 请点击edit然后点击[<>]stacksn-p编辑器并生成minimal reproducible example
  • 信息不足 - 请同时发布 getFeatures() 实现,就像 cluster 一样
  • 我猜getFeatures() 是异步的,类似于服务器请求?在这种情况下,您的 console.log() 将在 http 请求被解析之前执行
  • 请告诉我们你是如何尝试使用承诺的。
  • getFeatures() 很可能是一个 http 请求,因为特征是从地图中呈现的。明天我会提供更多信息和 stacksn-p!

标签: javascript arrays asynchronous foreach


【解决方案1】:

您实际上不需要内部 forEach,因为它只是将功能复制到可以使用 .push(...stuff) 完成的结果中,您必须承诺 getFeatures 然后才能在所有承诺上调用 Promise.all,等待他们全部完成:

const result = [];

const allDone = Promise.all(clusters.map((cluster) => new Promise(resolve => {
  getFeatures(cluster_id, (features) => {
    result.push(...features);
    resolve();
  });
})));

allDone.then(() => {
  // result is ready to use here
});

如果您需要按顺序排列结果,您可以用它们解决承诺,然后将结果展平:

 const allDone = Promise.all(clusters.map((cluster) => new Promise(resolve => {
  getFeatures(cluster_id, (features) => {
    resolve(features);
  });
})));

allDone.then((nestedResults) => {
  const result = nestedResults.flat();
  //...
});

【讨论】:

  • 效果很好!虽然我仍然不得不使用内部的 forEach,因为我需要访问一些特征属性。但是,您的解决方案对我有用!
【解决方案2】:

您可以将结果转换为 Promise,然后将解析后的数组展平:

Promise.all(clusters.map(cluster => new Promise(resolve => 
    getFeatures(cluster.id, resolve)
  ))
)
// as .flat() doesn't work in Node.js <= 10, this is a workaround:
//.then(clusterFeatures => clusterFeatures.reduce((acc,curr) => [...acc, ...curr], []))
.then(clusterFeatures => clusterFeatures.flat())
.then(features => ... );

【讨论】:

  • 只用clusterFeatures.flat(),没那么低效reduce :-)
  • @Bergi 我编辑了我的答案 - 作为 Node 10 用户,我不习惯使用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-11
  • 2021-03-09
  • 1970-01-01
  • 2019-11-04
  • 1970-01-01
  • 1970-01-01
  • 2016-08-16
相关资源
最近更新 更多