Как использовать promise в цикле forEach массива для заполнения объекта
я запускаю цикл forEach на массиве и делаю два вызова, которые возвращают обещания, и я хочу заполнить объект say this.options
, а затем сделайте с ним другие вещи. Прямо сейчас я сталкиваюсь с проблемой асинхронности, если я использую следующий пример кода, и я сначала попадаю в функцию then.
$.when.apply($, someArray.map(function(item) {
return $.ajax({...}).then(function(data){...});
})).then(function() {
// all ajax calls done now
});
это рабочий код ниже, но он работает только для первого элемента в массиве, потому что я называю полученной функции в .then
ответ. Я хочу сделать все сначала извлеките все элементы массива, а затем вызовите результирующую функцию, чтобы что-то сделать.
array.forEach(function(element) {
return developer.getResources(element)
.then((data) = > {
name = data.items[0];
return developer.getResourceContent(element, file);
})
.then((response) = > {
fileContent = atob(response.content);
self.files.push({
fileName: fileName,
fileType: fileType,
content: fileContent
});
self.resultingFunction(self.files)
}).catch ((error) = > {
console.log('Error: ', error);
})
});
Как заполнить self.files
object после завершения цикла forEach, а затем вызовите результирующую функцию с объектом files?
4 ответов
Promise.all()
будет полезно здесь:
var promises = [];
array.forEach(function(element) {
promises.push(
developer.getResources(element)
.then((data) = > {
name = data.items[0];
return developer.getResourceContent(element, file);
})
.then((response) = > {
fileContent = atob(response.content);
self.files.push({
fileName: fileName,
fileType: fileType,
content: fileContent
});
}).catch ((error) = > {
console.log('Error: ', error);
})
);
});
Promise.all(promises).then(() =>
self.resultingFunction(self.files)
);
это запускает вызов AJAX для каждого из элементов, добавляет результат каждого вызова в self.files
после завершения вызова и звонки self.resultingFunction()
после завершения всех вызовов.
Edit: упрощенный на основе предложений Юрия Тарабанко.
просто небольшое изменение принятого решения выше будет:
var promises = array.map(function(element) {
return developer.getResources(element)
.then((data) = > {
name = data.items[0];
return developer.getResourceContent(element, file);
})
.then((response) = > {
fileContent = atob(response.content);
self.files.push({
fileName: fileName,
fileType: fileType,
content: fileContent
});
}).catch ((error) = > {
console.log('Error: ', error);
})
});
Promise.all(promises).then(() =>
self.resultingFunction(self.files)
);
на этот ответ на аналогичный вопрос для отличной подсказки. Решение, данное там, использует Array#reduce()
чтобы избежать необходимости накапливать все обещания, прежде чем делать какую-либо работу, а не использовать Promise.all()
.
следующий код-это простое понимание синхронизации с помощью Promise.
let numArr = [1,2,3,4,5];
let nums=[];
let promiseList = new Promise(function(resolve,reject){
setTimeout(()=>{
numArr.forEach((val)=>{
nums.push(val);
});
resolve(nums);
},5000)
})
Promise.all([promiseList]).then((arrList)=>{
arrList.forEach((array)=>{
console.log("Array return from promiseList object ",array);
})
});
выше пример будет содержать array nums на 5 сек. и он будет печатать на консоли после его выпуска.