对递归数据结构的承诺

a promise for a recursive data structure

我想在调用控制器之前解析递归数据结构,但我正在为如何执行此操作而苦苦挣扎。

我当前的代码如下所示:

region.loadChildren = function() {
    region.children = [];
    return region.resource.all('children').getList().then(function(subs) {
        angular.forEach(subs, function(sub) {
            sub.loadChildren();
            region.children.push(sub);
        });
      }, errorCallback
    );
};

我能否以某种方式 "collect" sub.loadChildren() 返回的承诺并将它们合并?

是的,您可以使用 $q.all 将承诺收集到一个承诺中,该承诺在列表中的每个承诺都已解决时解决。

var promises = []
angular.forEach(subs, function(sub) {
  promises.push(sub.loadChildren());
  region.children.push(sub);
});
$q.all(promises).then(function(values) {
  // Finished
})

$q.all 是您的解决方案 -

region.loadChildren = function() {
    region.children = [];
    return region.resource.all('children').getList().then(function(subs) {
        var promises = subs.map(subs, function(sub) {
            var promise = sub.loadChildren();
            region.children.push(sub);
            return promise;
        });

        var allPromisesInOnePromise = $q.all(promises); // a regular promise which will resolve when all of the promises will resolve

      }, errorCallback
    );
};

您可以在此处阅读更多关于 promises 和 $q.all 函数的信息- https://docs.angularjs.org/api/ng/service/$q

您可以将当前函数替换为创建初始数组的函数,然后将其传递给执行实际工作的原始函数的修改版本:

region.loadChildren = function() {
    var tmp = [];
    this.loadChildrenHelper(tmp);
    this.children = tmp;
}

region.loadChildrenHelper = function(accum) {
    return region.resource.all('children').getList().then(function(subs) {
        angular.forEach(subs, function(sub) {
            sub.loadChildrenHelper(accum);
            accum.push(sub);
        });
      }, errorCallback
    );
};

然后在结果数组

上使用$q.all

使用 $q.all 合并承诺集合,并确保 return 它们用于 链接

region.loadChildren = function() {
    //return for chaining
    return region.resource.all('children').getList().then(function(subs) {
        var children = [];
        angular.forEach(subs, function(sub) {
            var p = sub.loadChildren();
            children.push(p);
        });
        //return for chaining
        return $q.all(children);
    );
};

因为调用承诺的 .then 方法 return 是一个新的派生承诺,所以很容易创建承诺链。可以创建任意长度的链,并且由于一个 promise 可以用另一个 promise 解决(这将进一步推迟其解决),因此可以 pause/defer 在链中的任何点解决 promise。这使得实现强大的 API 成为可能。1

有关详细信息,请参阅 AngularJS $q service API Reference -- chaining promises.

请注意 $q.all 没有弹性 。如果其中一个承诺被拒绝,$q.all 将解决第一个错误被拒绝的问题。