在Angular1.x中,$promise和$q promise有什么区别?

9

我开始在Angular中使用以下语法的Promise来解决我的api调用:

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

现在,我遇到了这样的情况:我必须在for循环中链接多个promises,并在所有promises都被解决后执行一些代码。我一直在尝试使用$promise语法来解决这个问题,但是大多数互联网上的资源都讲述了$q。我是一个新手,发现在这两个概念($q和$promise)之间转换非常困难。请求各位好心人:首先,向我解释一下$promise和$q之间的区别;其次,如果我决定使用$q来解决我的当前问题,是否意味着我将不得不重写使用$promise的代码以使其能够链式调用,例如$q.all()?

简短回答:$promise是某些操作返回值上的一个属性,它返回该操作结果的一个Promise。$q是一个服务,提供了一些Promise创建和操作机制,如$q.all$q.resolve - JLRishe
2个回答

7

$promise 是由 $resource Service 类型的操作方法返回的对象的一个属性。

重要的是要意识到调用 $resource 对象方法会立即返回一个空引用(对象或数组,具体取决于 isArray)。一旦数据从服务器返回,现有的引用将填充实际数据。
资源实例和集合还具有以下其他属性:
- $promise: 创建此实例或集合的原始服务器交互的 Promise。
在成功时,promise 会解析为相同的资源实例或集合对象,并使用来自服务器的数据进行更新。这使得在 $routeProvider.when() 的 resolve 部分 中使用它很容易,以推迟视图渲染直到资源加载完成。
在失败时,Promise 将被拒绝,并带有 http 响应 对象,但不包括资源属性。 --AngularJS $resource 服务 API 参考

注意:问题中的示例代码是多余且不必要的。

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

将解决的响应分配给$scope并不是必须的,因为当结果来自服务器时,$resource将自动填充引用。只有在代码需要处理结果之后,才使用$promise属性。
要区分返回$resource Service对象的服务和返回promises的其他服务,请查找.then方法。如果对象具有.then方法,则它是一个promise。如果它具有$promise属性,则遵循ngResource模式。

显然,您已经注意到了,我在$q.all()中使用了一个$resource.$promise的数组,它可以工作。

$q.all适用于任何来源的promises。在幕后,它使用$q.when将值或promises(任何then-able对象)转换为$q Service promises。

$q.all与其他promise库中的all方法不同之处在于,它不仅适用于数组,还适用于具有promise属性的JavaScript对象。可以创建一个promise哈希(关联数组)并使用$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异步获取的。

1
这真的很有帮助。对你来说可能很明显,但我在$q.all()中使用了$resource.$promise的数组,并且它起作用了。你的答案帮助我加强了我的概念理解。谢谢 :) - Apoorv Kesharwani

7
您可以通过调用$q来构建一个Angular中的Promise:
 let promise = $q(function(resolve, reject) { ... };

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

 let promise = $q.resolve(somevalue);

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

创建新Promise的最后一种方法是在现有Promise上调用.then()(或.catch())。

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

一旦您有了一些Promises,您可以将它们全部放入数组中,并使用$q.all()等待它们全部完成,或者等待其中一个被拒绝。或者,如果你想按顺序发生事情,你可以通过在前一个Promise的.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 ...});

谢谢您的答案 :) - Apoorv Kesharwani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接