简短回答:否
$resource 接口专门设计用于允许这种“期货”行为。当您调用 .get() 时,它会返回一个占位符对象,该对象将在可用时填充数据。
因为$resource 是一个内部 Angular 工厂,它知道何时触发摘要循环,这使得您似乎可以从一开始就使用$scope.user。实际上,在服务器发出 HTTP 响应之前,它不会填充数据。
另一方面,Promise 是一种通用机制。它不知道在它们到达时将其值存储在哪种占位符对象中。也不会到达什么样的值。因此,promise 公开了一系列回调方法,我们可以使用这些方法来让我们知道 promise 何时准备就绪。
长答案:排序(你可以使用 Promise 来构建像这样工作的接口)
这种机制之所以有效,是因为 Angular 对范围进行脏检查的方式。当异步发生时,需要让 Angular 知道它应该检查是否有任何变化,并且需要更新它的视图。
当数据从我们的 HTTP 响应到达时,$resource 工厂负责通知 Angular。这意味着$scope.user 对象一到达就会出现在您的视图中。 $resource 负责在异步事件发生时使事情发生。在这种情况下,异步事件是与数据一起到达的 HTTP 响应。
使用 Promise 时,您有责任在异步事件发生时让事情发生。它将是特定于 Angular 的 Promise,因此 Promise 有一个通用接口来处理可能发生在 Promise 上的不同异步事件。当其中一种情况发生时,您的工作就是完成这项工作,这就是为什么简短的回答是否定的。
但是,如果您正在实现需要这种行为的工厂/服务/提供者,这是可能的。
让我们创建一个创建火箭实例的火箭工厂,稍后将添加它们的零件,就像$resource 一样,使用$q 工厂。
app.factory('Rocket', function(Junkyard) {
return function(name) {
var rocket = {};
rocket.name = name || 'Boring Rocket';
rocket.parts = [];
rocket.promise = Junkyard.getParts();
// Junkyard.getParts returns a $q promise
// which will be resolved with an object
// of things that can be attached to the rocket.
//
// It might look something like this
// [
// { name: "thrusters", "quantity": 3 },
// { name: "engines", "quantity": 100 },
// { name: "robots", "quantity": 2 }
// ]
rocket.promise.then(function(parts) {
parts.forEach(function(part) {
rocket.parts.push(part);
});
});
return rocket;
};
});
现在我们可以像$resource一样使用我们的新工厂:
function MyController($scope, Rocket) {
$scope.rocket = Rocket('Top Rocket');
// we can use $scope.rocket here!
$scope.rocket.name = 'Even Better Rocket';
// but it won't have the properties from
// Junkyard.getParts yet.
}
我们可以将这些值直接模板化到我们的视图中。
<section ng-controller='MyController'>
<h1 ng-bind='rocket.name'></h1>
<table>
<th>
<td>Name</td>
</th>
<th>Description</th>
<tr ng-repeat='part in rocket.parts'>
<td ng-bind='part.name'></td>
<td ng-bind='part.description'></td>
</tr>
</table>
</section>
一旦 Promise 解决,属性将被添加到 Rocket 中,并且范围摘要将由 $q 触发,因为 $q 知道刚刚发生了异步事件。