我在一个数组上运行一个forEach循环并进行两次返回promises的调用,我想填充一个对象说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);
})
});
如何在forEach循环完成后填充self.files
对象,然后使用files对象调用生成的函数?
答案 0 :(得分:51)
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()
。
修改:根据Yury Tarabanko的建议进行简化。
答案 1 :(得分:18)
上面接受的解决方案只是略有变化:
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.map
代替Array.forEach
,这意味着我不需要先创建一个空数组,我只是重新使用现有的数组。
答案 2 :(得分:1)
您可以查看this answer to a similar question的优秀提示。给出的解决方案使用Array#reduce()
来避免在执行任何工作之前累积所有Promise而不是使用Promise.all()
。
答案 3 :(得分:1)
以下代码使用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);
})
});
以上示例将保持数组 nums 5秒。它会在发布后在控制台上打印出来。
答案 4 :(得分:0)
您可以使用.map
作为一个循环,对数组中的每个元素启动Promise请求,并返回这些Promise的新数组。
我也使用了解构,但不确定我们在这里需要它。
await Promise.all([...arr.map(i => "our promise func"())]);