$resource 'get' 函数如何在 AngularJS 中同步工作
How does the $resource `get` function work synchronously in AngularJS?
我正在观看这个AngularJS教程,该教程描述了如何使用Angular资源连接到Twitter。(视频教程) 下面是在示例控制器中设置的资源:
$scope.twitter = $resource('http://twitter.com/:action',
{action: 'search.json', q: 'angularjs', callback: 'JSON_CALLBACK'},
{get: {method: 'JSONP'}});
本教程演示了几种使用 get
调用从资源获取数据的方法。 第一种方法是将回调传递给 get 函数。 在 ajax 请求返回后,将调用回调并显示结果:
$scope.twitter.get(function(result) {
console.log('This was the result:', result);
});
我理解这种方法。 这对我来说非常有意义。 资源表示 Web 上可以获取数据的位置,get
只需对 url 进行 ajax 调用,获取 json,并使用 json 调用回调函数。 result
参数是 json。
这对我来说很有意义,因为很明显这是一个异步调用。 也就是说,在后台,ajax 调用会触发,并且调用后面的代码不会被阻止,而是继续执行。 然后在稍后的某个不确定点,当 xhr 成功时,将调用回调函数。
然后教程展示了一种看起来简单得多的不同方法,但我不明白它是如何工作的:
$scope.twitterResult = $scope.twitter.get();
我假设get
下面的 xhr 必须是异步的,但在这一行中,我们将get
调用的返回值分配给一个变量,就好像它是同步返回的一样。
我不明白这一点有错吗? 这怎么可能? 我认为它真的很好,我只是不明白。
我知道get
可以在它下面的 xhr 关闭并异步处理时返回一些东西,但如果你自己按照代码示例进行操作,你会看到$scope.twitterResult
在执行任何后续行之前获取实际的 Twitter 内容。 例如,如果您立即在该行之后写入console.log($scope.twitterResult)
,您将看到控制台中记录的 Twitter 结果,而不是稍后替换的临时值。
更重要的是,因为这是可能的,我如何编写一个利用相同功能的 Angular 服务? 除了 ajax 请求之外,还有其他类型的数据存储需要异步调用,这些调用可以在 JavaScript 中使用,我希望能够以这种风格同步编写代码。 例如,IndexedDB。 如果我能理解Angular的内置资源是如何做到的,我会试一试。
>$resource不是同步的,尽管此语法可能表明它是:
$scope.twitterResult = $scope.twitter.get();
这里发生的事情是,对 AngularJS 的调用将在调用 twitter.get()
后立即返回,结果是一个空数组。然后,当异步调用完成并且真实数据从服务器到达时,数组将使用数据进行更新。AngularJS将简单地保留对返回的数组的引用,并在数据可用时填充它。
以下是$resource实现中"魔术"发生的片段:https://github.com/angular/angular.js/blob/master/src/ngResource/resource.js#L372
这在$resource文档中也有描述:
重要的是要认识到,调用 $resource 对象方法会立即返回一个空引用(对象或数组取决于
isArray
)。从服务器返回数据后,将使用实际数据填充现有引用。这是一个有用的技巧,因为通常资源被分配给一个模型,然后由视图呈现。如果对象为空,则不会呈现,一旦数据从服务器到达,该对象就会填充数据,视图会自动重新呈现自身,显示新数据。这意味着在大多数情况下,永远不必为操作方法编写回调函数。
$q也可以做到这一点。您可以使用如下方法将普通对象转换为"延迟值":
var delayedValue = function($scope, deferred, value) {
setTimeout(function() {
$scope.$apply(function () {
deferred.resolve(value);
});
}, 1000);
return deferred.promise;
};
然后在控制器中使用它,以获得类似于 $scope.twitter.get() 在 OP 示例中所做的效果
angular.module('someApp', [])
.controller('someController', ['$scope', '$q', function($scope, $q) {
var deferred = $q.defer();
$scope.numbers = delayedValue($scope, deferred, ['some', 'numbers']);
}]);
- angularjs文本区域-如何使其与angularjs下拉列表中的选定值保持同步
- AngularJS:在使用嵌套的JQuery Sortables时保持Dom和Model同步
- $resource 'get' 函数如何在 AngularJS 中同步工作
- 使用AngularJS,如何在视图和控制器同步特定更改后触发代码执行
- AngularJS.ng类与$scope中的变量不同步
- AngularJs:在内部调用$http或$resource时,让方法同步返回
- 如何确保angularjs app.js中的同步加载
- 模型绑定在 AngularJS 中不同步
- $http.获取同步 AngularJS
- AngularJS将实时收集与REST同步,并获得实时更新
- 使用LoDash和AngularJS进行实时同步更新
- AngularJS中的同步$resource
- AngularJs:$http同步调用
- 使用AngularJS同步两个数组中的数据
- angularJS:将重新排序列表与数据结构同步
- 同步与服务链接的两个AngularJS控制器
- 如何从angularjs同步调用json数据
- 用Angularjs同步Leafletjs的地图数据
- AngularJS:同步多个独立的承诺
- 在表单提交之前与AngularJS同步调用服务器