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

时间:2022-03-25 12:11:34

I started using promises in angular for resolving my api calls with the following syntax:

我开始使用angular中的promises来解析我的api调用,使用以下语法:

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

Now, I have encountered a situation where I have to chain multiple promises in a for loop and execute some code once all the promises in the for loop have been resolved. I have been trying to search for how to do this with the $promise syntax, but most sources on the internet talk about $q. I am new into development work and am finding it very confusing to juggle between these two concepts ($q and $promise). Request you nice folks to: first, explain to me the difference between $promise and $q; second, if I decide to use $q for solving my present problem as described above, does it mean I will have to rewrite the code that used $promise in order to make it chainable with something like $q.all()?

现在,我遇到了一种情况,我必须在for循环中链接多个promise并在for循环中的所有promise都已解析后执行一些代码。我一直试图用$ promise语法搜索如何做到这一点,但互联网上的大多数消息来源都在谈论$ q。我是开发工作的新手,我发现在这两个概念($ q和$ promise)之间徘徊是非常困惑的。请你们好心人:首先,向我解释$ promise和$ q之间的区别;第二,如果我决定使用$ q来解决我上面描述的当前问题,是否意味着我将不得不重写使用$ promise的代码,以使其可以像$ q.all()那样链接?

2 个解决方案

#1


4  

You can construct a promise in angular by calling $q:

您可以通过调用$ q来构造角度的承诺:

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

or if you simply want a promise that resolves immediately:

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

 let promise = $q.resolve(somevalue);

There is also an older way using $q.defer() to construct a deferred object and returning it's .promise attribute, but you should probably avoid doing it that way and consider it just for backward compatibility.

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

The final way to create a new promise is to call .then() (or .catch()) on an existing promise.

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

The .$promise attribute is simply a promise created by one of the above mechanisms either by the $resource service or by something following the same pattern.

。$ promise属性只是上述机制之一由$ resource服务或遵循相同模式的东西创建的promise。

Once you have some promises you can stuff them all into an array and use $q.all() to wait for them all to complete, or for one to reject. Or if you want things to happen sequentially you can chain them together by performing each step in the .then() of the previous promise:

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

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

That will execute everything in sequence whereas $q.all() starts them off in parallel. Sometimes you want one, sometimes the other:

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

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

#2


5  

$promise is a property of objects returned by the $resource Service class-type action methods.

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

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.

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

The Resource instances and collections have these additional properties:

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

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

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

    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.

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

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

    失败时,使用http响应对象拒绝promise,不使用resource属性。

--AngularJS $resource Service API Reference

--AngularJS $资源服务API参考


Note: The example code in the question is redundant and unnecessary.

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

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

The assignment of resolved responses to $scope is not necesssary as the $resource will automatically populate the reference when the results come from the server. Use the $promise property only when code needs to work with results after they come from the server.

分配给$ scope的已解决响应不是必需的,因为$ resource会在结果来自服务器时自动填充引用。仅当代码需要在来自服务器后使用结果时才使用$ promise属性。

To distinguish services which return $resource Service objects from other services which return promises, look for a .then method. If the object has a .then method, it is a promise. If it has a $promise property, it follows the ngResource pattern.

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



It must be obvious to you, but I used an array of $resource.$promise's inside $q.all() and it worked.

对你来说一定是显而易见的,但我在$ 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 promises.

$ q.all适用于任何来源的承诺。在引擎盖下,它使用$ q.when将值或承诺(任何可用的对象)转换为$ q服务承诺。

What sets $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 to resolve it.

将$ q.all与其他promise库中的all方法区分开来的是,除了使用数组之外,它还适用于具有promises属性的JavaScript对象。可以制作promises的哈希(关联数组)并使用$ 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
});

The above example creates a hash of items indexed by itemName with all the items being fetched asynchronously from a $resource Service.

上面的示例创建了一个由itemName索引的项的哈希,所有项都是从$ resource Service异步提取的。

#1


4  

You can construct a promise in angular by calling $q:

您可以通过调用$ q来构造角度的承诺:

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

or if you simply want a promise that resolves immediately:

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

 let promise = $q.resolve(somevalue);

There is also an older way using $q.defer() to construct a deferred object and returning it's .promise attribute, but you should probably avoid doing it that way and consider it just for backward compatibility.

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

The final way to create a new promise is to call .then() (or .catch()) on an existing promise.

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

The .$promise attribute is simply a promise created by one of the above mechanisms either by the $resource service or by something following the same pattern.

。$ promise属性只是上述机制之一由$ resource服务或遵循相同模式的东西创建的promise。

Once you have some promises you can stuff them all into an array and use $q.all() to wait for them all to complete, or for one to reject. Or if you want things to happen sequentially you can chain them together by performing each step in the .then() of the previous promise:

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

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

That will execute everything in sequence whereas $q.all() starts them off in parallel. Sometimes you want one, sometimes the other:

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

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

#2


5  

$promise is a property of objects returned by the $resource Service class-type action methods.

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

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.

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

The Resource instances and collections have these additional properties:

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

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

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

    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.

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

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

    失败时,使用http响应对象拒绝promise,不使用resource属性。

--AngularJS $resource Service API Reference

--AngularJS $资源服务API参考


Note: The example code in the question is redundant and unnecessary.

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

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

The assignment of resolved responses to $scope is not necesssary as the $resource will automatically populate the reference when the results come from the server. Use the $promise property only when code needs to work with results after they come from the server.

分配给$ scope的已解决响应不是必需的,因为$ resource会在结果来自服务器时自动填充引用。仅当代码需要在来自服务器后使用结果时才使用$ promise属性。

To distinguish services which return $resource Service objects from other services which return promises, look for a .then method. If the object has a .then method, it is a promise. If it has a $promise property, it follows the ngResource pattern.

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



It must be obvious to you, but I used an array of $resource.$promise's inside $q.all() and it worked.

对你来说一定是显而易见的,但我在$ 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 promises.

$ q.all适用于任何来源的承诺。在引擎盖下,它使用$ q.when将值或承诺(任何可用的对象)转换为$ q服务承诺。

What sets $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 to resolve it.

将$ q.all与其他promise库中的all方法区分开来的是,除了使用数组之外,它还适用于具有promises属性的JavaScript对象。可以制作promises的哈希(关联数组)并使用$ 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
});

The above example creates a hash of items indexed by itemName with all the items being fetched asynchronously from a $resource Service.

上面的示例创建了一个由itemName索引的项的哈希,所有项都是从$ resource Service异步提取的。