我的应用程序中存在流量控制问题。我有一个分层的(类似家庭的)数据结构,类似于:
{name: "Bob", children: [{name: "Tim", children: [..]}, {another child..}]}
此结构可能有很多层次。
现在我要做的是递归地遍历所有人,获取他们的ID,进行api调用以检索此人的图片。
伪代码:
gatherPicture(hierarchy);
console.log("I want to wait before doing this!") // Logs too early
function gatherPicture(person) {
// api request (promise)
getPicture(person.id).then(r => {
person.picture = r;
person.children.forEach(gatherPicture);
})
}
希望该代码有意义。如何让我的代码等待,直到collectPicture函数处理并解决了所有人的问题?
如果添加了任何内容,则说明我正在使用AngularJS,并且可以访问可用的$ q promise服务。但是我只是不了解如何设置这个特定的promise链,因为它们是在递归函数内部构建的。
非常感谢!
答案 0 :(得分:3)
关键是使用$q.all
和Array.prototype.map
gatherPicture(hierarchy)
.then(() => {
console.log("I want to wait before doing this!")
})
function gatherPicture(person) {
// api request (promise)
return getPicture(person.id).then(r => {
person.picture = r;
return $q.all(person.children.map(gatherPicture));
})
}
因此,首先从getPicture
的{{1}}返回Promise链,这样您就可以建立适当的Promise链。
然后下一步是,您使用gatherPicture
为所有孩子创建一个Promises列表,然后等待使用person.children.map(gatherPicture)
来解决它
答案 1 :(得分:0)
gatherPicture = (person) => {
getPicture(person.id)
.then(data => {
person.picture = data;
return Promise.all(person.children.map(gatherPicture));
})
}
答案 2 :(得分:0)
另一种方法可能是先将树展平:
const flatten = (tree) => (tree.children || [])
.reduce((flattened, child) => flattened.concat(flatten(child)), [])
.concat(tree);
然后,给出一个简单的gatherPicture
函数:
const gatherPicture = (person) => getPicture(person.id).then((picture) => {
person.picture = picture;
});
您可以轻松地等待它们全部完成,同时:
const gatherPictures = (tree) => Promise.all(flatten(tree).map(gatherPicture));
使用:
gatherPictures(hierarchy).then(() => {
console.log("Done");
});