Javascript 如何在数组的forEach循环中使用promise来填充对象
我在一个数组上运行一个forEach循环,并进行两个返回承诺的调用,我想填充一个对象,比如说Javascript 如何在数组的forEach循环中使用promise来填充对象,javascript,arrays,foreach,promise,es6-promise,Javascript,Arrays,Foreach,Promise,Es6 Promise,我在一个数组上运行一个forEach循环,并进行两个返回承诺的调用,我想填充一个对象,比如说this.options,然后用它做其他事情。现在,如果我使用下面的代码示例并首先进入then函数,我将遇到异步问题 $.when.apply($, someArray.map(function(item) { return $.ajax({...}).then(function(data){...}); })).then(function() { // all ajax calls do
this.options
,然后用它做其他事情。现在,如果我使用下面的代码示例并首先进入then函数,我将遇到异步问题
$.when.apply($, someArray.map(function(item) {
return $.ajax({...}).then(function(data){...});
})).then(function() {
// all ajax calls done now
});
这是下面的工作代码,但它只适用于数组中的第一个元素,因为我在响应的中调用结果函数。我想首先对数组的所有元素执行所有的fetch,然后调用结果函数来执行一些操作
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对象调用结果函数 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的建议进行简化。上述公认解决方案的一个细微变化就是:
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
,这意味着我不需要先创建一个空数组,我只需要重新使用现有的数组。您可能会看到一个很好的提示。这里给出的解决方案使用Array#reduce()
来避免在执行任何工作之前必须累积所有承诺,而不是使用Promise.all()
以下代码是对使用承诺同步的简单理解
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);
})
});
上面的示例将保持arraynums5秒。发布后会在控制台上打印 您可以使用.map
作为一个周期,为数组的每个元素启动承诺请求,并返回这些承诺的新数组。
我还使用了解构,但不确定这里是否需要它
await Promise.all([...arr.map(i => "our promise func"())]);
当你显然需要地图时,为什么要forEach
?@YuryTarabanko我用了一张地图,但那也没用。我在回答中也尝试了这种方法,但使用了$.when.apply($,promissions).then()
,但也不起作用。我认为它不起作用,因为我没有按照ES6的方式来做。应该是承诺。所有的,而不是承诺(复数)。为什么要手动创建承诺?看起来getResources
已经返回了one@YuryTarabanko出于好奇,如果您将从getResources
返回的承诺直接推送到promissions
数组,而不是将其包装在自己的数组中,是否保证在Promise.all()
的终结处理程序之前先调用所有单个终结处理程序?如果不是,那么创建您自己的承诺似乎是必要的。@TimoSta不是直接从getResources
获得的,而是您在chaingetResources().then(fn1).then(fn2).catch()中得到的最后一个承诺。每次你打电话给,你就会得到一个新的承诺。并且确保将在fn2
之前和终结处理程序之前调用fn1
。因为承诺会将fn1的结果传递给fn2,然后传递给终结处理程序(作为相应的数组元素)。今天学到了新东西!谢谢:-)您能强调一下您所做的更改吗,这样我们就不必阅读每一行了?我们在结尾添加了一个新的句子来解释我所做的事情。虽然此代码可以回答问题,但提供有关此代码为什么和/或如何回答问题的其他上下文可以提高其长期价值。