angular1.x 中的 $promise 和 $q promises 有什么区别?

What is the difference between $promise and $q promises in angular1.x?

我开始使用 angular 中的承诺来解决我的 api 调用,语法如下:

 $scope.module = moduleFactory.get({id: $stateParams.id})
    .$promise.then(function(response){
        $scope.module = response;
     }

现在,我遇到了一种情况,我必须在一个 for 循环中链接多个 promise,并在 for 循环中的所有 promise 都已解决后执行一些代码。我一直在尝试寻找如何使用 $promise 语法执行此操作,但互联网上的大多数资源都在谈论 $q。我是开发工作的新手,发现在这两个概念($q 和 $promise)之间游刃有余非常混乱。请各位好心人:首先,向我解释一下 $promise 和 $q 之间的区别;其次,如果我决定使用 $q 如上所述解决我目前的问题,这是否意味着我将不得不重写使用 $promise 的代码以使其可与 $q.all() 之类的东西链接?

$promise 是 属性 个对象 return,由 $resource Service class 类型的操作方法编辑。

It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data.

The Resource instances and collections have these additional properties:

  • $promise: the promise of the original server interaction that created this instance or collection.

    On success, the promise is resolved with the same resource instance or collection object, updated with data from server. This makes it easy to use in resolve section of $routeProvider.when() to defer view rendering until the resource(s) are loaded.

    On failure, the promise is rejected with the http response object, without the resource property.

--AngularJS $resource Service API Reference


注意:问题中的示例代码是多余的,没有必要。

$scope.module = moduleFactory.get({id: $stateParams.id})
    .$promise.then(function(response){
        //REDUNDANT, not necessary
        //$scope.module = response;
    });

将已解决的响应分配给 $scope 不是必需的,因为 $resource will automatically populate the reference when the results come from the server. Use the $promise 属性 只有当代码需要处理结果 after 它们来自服务器。

要区分 return $resource Service 对象的服务与 return 承诺的其他服务,请寻找 .then 方法。如果对象有一个 .then 方法,它就是一个 promise。如果它有 $promise 属性,它遵循 ngResource 模式。



这对你来说一定很明显,但我在 $q.all() 中使用了一个 $resource.$promise 数组并且它起作用了。

$q.all works with promises from any source. Under the hood, it uses $q.when to convert values or promises (any then-able object) to $q Service 承诺。

什么设置 $q.all apart from the all method in other promise libraries is that in addition to working with arrays, it works with JavaScript objects that have properties that are promises. One can make a hash (associative array) of promises and use $q.all 来解决它。

var resourceArray = resourceService.query(example);

var hashPromise = resourceArray.$promise.then(function(rArray) {
    promiseHash = {};
    angular.forEach(rArray,function (r) {
        var item = resourceService.get(r.itemName);
        promiseHash[r.itemName] = item.$promise;
    });
    //RETURN q.all promise to chain
    return $q.all(promiseHash);
});

hashPromise.then(function (itemHash) {
    console.log(itemHash);
    //Do more work here
});

上面的示例创建了一个由 itemName 索引的项目的散列,所有项目都是从 $resource Service.

异步获取的

您可以通过调用 $q:

在 angular 中构建承诺
 let promise = $q(function(resolve, reject) { ... };

或者如果您只是想要一个立即解决的承诺:

 let promise = $q.resolve(somevalue);

还有一种使用 $q.defer() 构造延迟对象并返回它的 .promise 属性的旧方法,但您可能应该避免这样做,并考虑它只是为了向后兼容。

创建新承诺的最后一种方法是对现有承诺调用 .then()(或 .catch())。

.$promise 属性只是由 $resource 服务或遵循相同模式的某些机制通过上述机制之一创建的承诺。

一旦你有了一些承诺,你就可以将它们全部填充到一个数组中,然后使用 $q.all() 等待它们全部完成,或者等待一个被拒绝。或者,如果您希望事情按顺序发生,您可以通过执行前一个承诺的 .then() 中的每个步骤将它们链接在一起:

 let promise = $q.resolve();
 for(... something ...) {
     promise = promise.then(() => { ... next step here ...});
 }
 promise.then(() => { ... runs when everything completed ...});

这将按顺序执行所有内容,而 $q.all() 将它们并行启动。有时你想要一个,有时你想要另一个:

 let promises = [];
 for(... something ...) {
     promises.push(somethingThatReturnsAPromise());
 }
 $q.all(promises).then(() => { ... runs when everything completed ...});