等待.forEach()完成的最佳方式

时间:2016-07-16 01:41:09

标签: javascript angularjs

有时我需要等待.forEach()方法完成,主要是在#loader;#功能。这就是我这样做的方式:

cygpath

我无法帮助,但我觉得这不是等待.forEach()完成的最好方法。这样做的最佳方式是什么?

12 个答案:

答案 0 :(得分:31)

var foo = [1,2,3,4,5,6,7,8,9,10];

如果你真的在循环中做异步内容,你可以把它包装在一个承诺中......

var bar = new Promise((resolve, reject) => {
    foo.forEach((value, index, array) => {
        console.log(value);
        if (index === array.length -1) resolve();
    });
});

bar.then(() => {
    console.log('All done!');
});

答案 1 :(得分:10)

board[1][1] = '*' 不是异步的,例如在此代码中:

forEach

array.forEach(function(item){ //iterate on something }); alert("Foreach DONE !"); 完成后,您会看到提醒。

答案 2 :(得分:6)

使用ES6进行这项工作的最快方法就是使用for..of循环。

const myAsyncLoopFunction = async (array) {
  const allAsyncResults = []

  for (const item of array) {
    const asnycResult = await asyncFunction(item)
    allAsyncResults.push(asyncResult)
  }

  return allAsyncResults
}

或者您可以使用Promise.all()并行遍历所有这些异步请求,如下所示:

const myAsyncLoopFunction = async (array) {
  const promises = array.map(asyncFunction)
  await Promise.all(promises)
  console.log(`All async tasks complete!`)
}

答案 3 :(得分:5)

如果您在循环中有一个异步任务并且您想等待。您可以使用 for await

for await (const i of images) {
    let img = await uploadDoc(i);
};

let x = 10; //this executes after

答案 4 :(得分:1)

在每个可能的唯一代码分支(包括回调)的末尾更改并检查一个计数器。示例:

.searchcontainer {
          text-align:center;
          width: 100%;
          max-width: 600px;
          margin: 0 auto;
       }

       .searchcontainer .search-part {
          display: flex;
          flex-direction: row;
          justify-content: center;
          align-items: center;
       }

      mat-form-field.mat-form-field {
          font-size: 12px;
          width: 300px;
      }

      button.mat-stroked-button {
          font-size: 14px;
          height: 42px;
          margin: 10px;
      }

答案 5 :(得分:1)

用于确保所有forEach()元素完成执行的通用解决方案。

const testArray = [1,2,3,4]
let count = 0

await new Promise( (resolve) => {
  testArray.forEach( (num) => {
    try {
      //some real logic
      num = num * 2
    } catch (e) {
      // error handling
      console.log(e)
    } fanally {
      // most important is here
      count += 1
      if (count == testArray.length) {
        resolve()
      }
    }
  })  
})

这个想法与使用索引计数的答案相同。但是在实际情况下,如果发生错误,索引方式将无法正确计数。因此该解决方案更加健壮。

Thx

答案 6 :(得分:0)

forEach()不返回任何内容,因此更好的做法是map() + Promise.all()

var arr = [1, 2, 3, 4, 5, 6]

var doublify = (ele) => {
  return new Promise((res, rej) => {
    setTimeout(() => {
        res(ele * 2)
    }, Math.random() ); // Math.random returns a random number from 0~1
  })
}

var promises = arr.map(async (ele) => {
  // do some operation on ele
  // ex: var result = await some_async_function_that_return_a_promise(ele)
  // In the below I use doublify() to be such an async function

  var result = await doublify(ele)
  return new Promise((res, rej) => {res(result)})
})

Promise.all(promises)
.then((results) => {
  // do what you want on the results
  console.log(results)
})

output

答案 7 :(得分:0)

与其他版本相比,我不确定此版本的效率,但是最近在我的forEach()中具有异步函数时才使用此版本。它不使用promise,映射或for-of循环:

// n'th triangular number recursion (aka factorial addition)
function triangularNumber(n) {
    if (n <= 1) {
        return n
    } else {
        return n + triangularNumber(n-1)
    }
}

// Example function that waits for each forEach() iteraction to complete
function testFunction() {
    // Example array with values 0 to USER_INPUT
    var USER_INPUT = 100;
    var EXAMPLE_ARRAY = Array.apply(null, {length: USER_INPUT}).map(Number.call, Number) // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, n_final... ] where n_final = USER_INPUT-1

    // Actual function used with whatever actual array you have
    var arrayLength = EXAMPLE_ARRAY.length
    var countMax = triangularNumber(arrayLength);
    var counter = 0;
    EXAMPLE_ARRAY.forEach(function(entry, index) {
        console.log(index+1); // show index for example (which can sometimes return asynchrounous results)

        counter += 1;
        if (triangularNumber(counter) == countMax) {

            // function called after forEach() is complete here
            completionFunction();
        } else {
            // example just to print counting values when max not reached
            // else would typically be excluded
            console.log("Counter index: "+counter);
            console.log("Count value: "+triangularNumber(counter));
            console.log("Count max: "+countMax);
        }
    });
}
testFunction();

function completionFunction() {
    console.log("COUNT MAX REACHED");
}

答案 8 :(得分:0)

我不得不处理相同的问题( forEach ,其中使用了多个promise ),而当前提出的解决方案都没有对我有帮助。因此,我实现了一个检查数组,每个诺言都会更新其完整状态。我们有一个概括整个过程的总体承诺。我们仅在每个承诺完成时解决一般承诺。代码段:

function WaitForEachToResolve(fields){

    var checked_fields = new Array(fields.length).fill(0);
    const reducer = (accumulator, currentValue) => accumulator + currentValue;

    return new Promise((resolve, reject) => {

      Object.keys(fields).forEach((key, index, array) => {

        SomeAsyncFunc(key)
        .then((result) => {

            // some result post process

            checked_fields[index] = 1;
            if (checked_fields.reduce(reducer) === checked_fields.length)
                resolve();
        })
        .catch((err) => {
            reject(err);
        });
      }
    )}
}

答案 9 :(得分:0)

const array = [1, 2, 3];
const results = [];
let done = 0;

const asyncFunction = (item, callback) =>
  setTimeout(() => callback(item * 10), 100 - item * 10);

new Promise((resolve, reject) => {
  array.forEach((item) => {
    asyncFunction(item, (result) => {
      results.push(result);
      done++;
      if (done === array.length) resolve();
    });
  });
}).then(() => {
  console.log(results); // [30, 20, 10]
});

// or
// promise = new Promise(...);
// ...
// promise.then(...);

“结果”数组中结果的顺序可能与原始数组中项目的顺序不同,具体取决于asyncFunction()完​​成每个项目的时间。

答案 10 :(得分:0)

您可以使用它,因为我们在 forEach 循环内使用 async/await。您可以在循环内使用自己的逻辑。

    let bar = new Promise((resolve, reject) => {
        snapshot.forEach(async (doc) => {
            """Write your own custom logic and can use async/await
            """
            const result = await something()
            resolve(result);
        });
    });
    let test = []
    test.push(bar)
    let concepts = await Promise.all(test);
    console.log(concepts);

答案 11 :(得分:0)

对于简单的比较代码,我喜欢使用 for 语句。

transport not available