我开始使用angular中的promises来解析我的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()那样进行链接?
答案 0 :(得分:5)
$promise
是$resource Service类类型操作方法返回的对象的属性。
重要的是要意识到调用
$resource
对象方法会立即返回一个空引用(对象或数组,具体取决于isArray
)。从服务器返回数据后,将使用实际数据填充现有引用。资源实例和集合具有以下附加属性:
$promise
:创建此实例或集合的原始服务器交互的承诺。成功时,promise将使用相同的资源实例或集合对象解析,并使用来自服务器的数据进行更新。这使得在resolve section of $routeProvider.when()中使用它很容易推迟视图渲染,直到资源被加载。
失败时,使用http response对象拒绝承诺,但没有资源属性。
注意:问题中的示例代码是多余的,不必要。
$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
属性,则它遵循ngResource模式。
对你来说一定是显而易见的,但我在$ {3}}中使用了一个$ resource。$ promise的数组,并且它有效。
$q.all()适用于来自任何来源的承诺。在幕后,它使用$q.all将值或承诺(任何可用的对象)转换为$q.when承诺。
除了使用其他promise库中的all
方法之外,$q Service除了使用数组之外,它还适用于具有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
});
上面的示例创建了一个由itemName索引的项的哈希,所有项都是从$q.all异步提取的。
答案 1 :(得分:4)
您可以通过调用$q
来构建角度的承诺:
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 ...});