Ожидание завершения нескольких операторов for-each - PullRequest
1 голос
/ 26 марта 2019

У меня есть массив кластеров, где каждый кластер содержит набор функций. Я использую два оператора forEach для итерации по кластерам и функциям, чтобы сохранить каждую функцию в моем массиве «result».

Мне нужно продолжить обработку моего массива "result". Но когда я спрашиваю о длине массива, утверждается, что длина равна 0, хотя я вижу в консоли, что в нем есть функции. Мне нужно найти способ обрабатывать массив «result» только после завершения цикла 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

Ответы [ 2 ]

1 голос
/ 26 марта 2019

На самом деле вам не нужен внутренний 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();
  //...
});
0 голосов
/ 26 марта 2019

Вы можете преобразовать результаты в 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 => ... );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...