【问题标题】:What is the difference between $promise and $q promises in angular1.x?angular1.x 中的 $promise 和 $q 承诺有什么区别?
【发布时间】:2017-07-16 06:31:23
【问题描述】:

我开始使用 Angular 中的 Promise 来解决我的 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 是某些操作返回值的属性,它返回对该操作结果的承诺。 $q 是一项服务,它提供了一些 Promise 创建和操作机制,例如 $q.all 和 $q.resolve。

标签: angularjs promise angular-promise angular-resource


【解决方案1】:

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

重要的是要意识到调用$resource 对象方法会立即返回一个空引用(对象或数组取决于isArray)。从服务器返回数据后,现有引用将填充实际数据。

Resource 实例和集合具有以下附加属性:

  • $promise:创建此实例或集合的原始服务器交互的承诺。

    成功时,promise 将使用相同的资源实例或集合对象进行解析,并使用来自服务器的数据进行更新。这使得在resolve section of $routeProvider.when() 中使用它可以很容易地推迟视图渲染,直到资源加载完成。

    失败时,promise 被 http response 对象拒绝,没有资源属性。

--AngularJS $resource Service API Reference


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

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

没有必要将已解析响应分配给 $scope,因为当结果来自服务器时,$resource 将自动填充引用。仅当代码需要处理来自服务器的结果之后时,才使用$promise 属性。

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



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

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

$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 异步获取的。

【讨论】:

  • 这真的很有帮助。这对您来说一定很明显,但我在 $q.all() 中使用了一个 $resource.$promise 数组并且它起作用了。你的回答帮助我加强了我的概念理解。谢谢:)
【解决方案2】:

你可以通过调用$q来构造一个角度的promise:

 let promise = $q(function(resolve, reject) { ... };

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

 let promise = $q.resolve(somevalue);

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

创建新 Promise 的最后一种方法是在现有 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 ...});

【讨论】:

  • 感谢您的回答:)
猜你喜欢
  • 2014-11-19
  • 2017-11-15
  • 1970-01-01
  • 2017-07-10
  • 2012-12-24
  • 1970-01-01
  • 1970-01-01
  • 2011-10-14
  • 2015-05-12
相关资源
最近更新 更多