Ответ 1
forEach
не является асинхронным, например, в этом коде:
array.forEach(function(item){
//iterate on something
});
alert("Foreach DONE !");
вы увидите предупреждение после того, как forEach
закончил.
Иногда мне нужно дождаться завершения метода.forEach(), в основном по функциям "loader". Так я это делаю:
$q.when(array.forEach(function(item){
//iterate on something
})).then(function(){
//continue with processing
});
Я не могу не чувствовать, что это не лучший способ дождаться завершения.forEach(). Каков наилучший способ сделать это?
forEach
не является асинхронным, например, в этом коде:
array.forEach(function(item){
//iterate on something
});
alert("Foreach DONE !");
вы увидите предупреждение после того, как forEach
закончил.
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!');
});
Самый быстрый способ заставить эту работу работать с 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!')
}
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)
})
Я не уверен в эффективности этой версии по сравнению с другими, но я использовал это недавно, когда у меня была асинхронная функция внутри моего forEach(). Он не использует обещания, отображение или циклы 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");
}
Нет, он блокирует. Посмотрите на спецификацию алгоритма.
Так что независимо от того, какой код, который вы ставите вне forEach, будет выполняться после завершения foEach().
array.forEach(function(item){
//iterate on something
})
// @TODO this code will be executed once above block is done.