[英]How do I use Promise.all() to defer returning an array that's being built inside the function?
Below I'm attempting to assign a value, an array, to a local variable. 下面,我尝试将一个值(数组)分配给局部变量。 I'm calling a function that returns an array to get that value. 我正在调用一个返回数组以获取该值的函数。 The problem is that the Promises
in the 2nd function aren't resolved until after the array has been returned to the caller. 问题在于,直到将数组返回给调用方之后,第二个函数中的Promises
才被解析。 I've tried using Promise.all()
on retArray
but it never works for me. 我已经尝试过在retArray
上使用Promise.all()
,但它对我永远都retArray
。 When I console.log()
out my someobject
object the arrOfTitles
field never prints out because the call to SkywalkerTitles()
returns an empty array . 当我console.log()
退出我的someobject
对象时, arrOfTitles
字段永远不会打印出来,因为对SkywalkerTitles()
的调用返回了一个空数组 。
You can run the code here . 您可以在此处运行代码。
So how do I get someObject.arrOfTitles
to get the array of titles from SkywalkerTitles()
? 那么,如何获取someObject.arrOfTitles
以从SkywalkerTitles()
获取标题数组?
function SkywalkerTitles(){
let retArray = [];
fetch('https://swapi.co/api/people/')
.then(function(response){
response.json()
.then(function(result){
return result.results[0];
})
.then(function(result){
result.films.forEach(function(film){
fetch(film)
.then(function(response){
response.json().then(function(result){
console.log(result.title);
retArray.push(result.title);
});
});
})
.catch(function(error){
console.log(error)
});
});
})
.catch(function(error){
console.log(error)
});
}
function UseReturnedArray() {
let someObject = { aThing: '', anotherThing: '', arrOfTitles: null };
someObject.aThing = 'Thing One';
someObject.anotherThing = 'Thing Two';
someObject.arrOfTitles = SkywalkerTitles();
console.log('Object With Returned Array:\n\n', JSON.stringify(someObject, null, 2));
}
UseReturnedArray();
You should take advantage of async/await, which could really clean up your code quite a bit and make it more understandable: 您应该利用async / await的优势,这实际上可以清理代码并使其更易于理解:
async function SkywalkerTitles () {
let character = await fetch('https://swapi.co/api/people/').then(res => res.json()).then(res => res.results[0])
return await Promise.all(character.films.map(async (film) => {
return await fetch(film).then(res => res.json()).then(res => res.title)
}))
}
async function UseRetrunedArray () {
try {
let someObject = {
aThing: '',
anotherThing: '',
arrOfTitles: await SkywalkerTitles()
}
console.log(someObject)
} catch (e) {
console.error(e)
}
}
UseRetrunedArray()
See https://repl.it/Lc2f/2 参见https://repl.it/Lc2f/2
If this looks alien to you, I suggest you read a bit into how async
/ await
and Promise
work together. 如果您觉得这有些陌生,建议您阅读一下async
/ await
和Promise
如何一起工作。
As much as @Svenskunganka answer is complete and worthy, alternative if your environment doesn't yet support async/await AND you don't want to use a transpiler - seeing as you're already partially familiar with Promises, this code shouldn't look as foreign :p @Svenskunganka的回答是完整和有价值的,如果您的环境尚不支持异步/等待并且您不想使用转译器,则可以选择-看到您已经对Promises有所了解,则此代码不应看起来像外国:p
Your main problem is that SkywalkerTitles doesn't actually return anything (you claim it returns an empty array, it actually has no return statement, therefore the returned value is undefined
您的主要问题是SkywalkerTitles实际上没有返回任何内容(您声称它返回了一个空数组,它实际上没有return语句,因此返回的值是undefined
I've also removed the .catch
code, because where you had it would actually cause issues, in that your code handles rejections, yet further down the chain the code would expect that the data was actually valid! 我还删除了.catch
代码,因为在该代码中,它实际上会引起问题,因为您的代码可以处理拒绝,但在链的更下游,代码将期望数据实际上是有效的! Only a single catch almost always ever needed 几乎只需要一次捕获
function SkywalkerTitles() {
return fetch('https://swapi.co/api/people/').then(function (response) {
return response.json();
}).then(function (result) {
return result.results[0];
}).then(function (result) {
return Promise.all(result.films.map(function (film) {
return fetch(film).then(function (response) {
return response.json();
}).then(function (result) {
return result.title;
});
}));
});
}
function UseReturnedArray() {
SkywalkerTitles().then(function (arrOfTitles) {
var someObject = {
aThing: '',
anotherThing: '',
arrOfTitles: arrOfTitles
};
console.log('Object With Returned Array:\n\n', JSON.stringify(someObject, null, 2));
}).catch(function(reason) {
console.log(reason);
});
}
UseReturnedArray();
Note how the promise chain is flattened compared to yours, and use of Array#map
instead of Array#forEach + Array#push
请注意,与您的相比,promise链如何展平,并使用Array#map
代替Array#forEach + Array#push
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.