如何从AngularJS中的异步树状结构API创建承诺

时间:2018-08-21 13:43:05

标签: javascript angularjs recursion promise

如何等待不确定的递归承诺解决

我的应用程序中存在流量控制问题。我有一个分层的(类似家庭的)数据结构,类似于:

{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链,因为它们是在递归函数内部构建的。

非常感谢!

3 个答案:

答案 0 :(得分:3)

关键是使用$q.allArray.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");
});