$resource `get` 函数如何在 AngularJS 中同步工作? [英] How does the $resource `get` function work synchronously in AngularJS?

查看:25
本文介绍了$resource `get` 函数如何在 AngularJS 中同步工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在观看 this AngularJS 教程,该教程描述了如何使用角资源.(视频教程)以下是​​示例控制器中设置的资源:

$scope.twitter = $resource('http://twitter.com/:action',{动作:'search.json',q:'angularjs',回调:'JSON_CALLBACK'},{get: {method: 'JSONP'}});

本教程展示了使用 get 调用从资源中取回数据的几种方法.第一种方法是将回调传递给 get 函数.ajax 请求返回后,会根据结果调用回调:

$scope.twitter.get(function(result) {console.log('这是结果:', result);});

我理解这种方法.这对我来说很有意义.资源代表网络上可以获取数据的地方,get 只是简单地对一个 url 进行 ajax 调用,返回 json,并使用 json 调用回调函数.result 参数是那个 json.

这对我来说很有意义,因为很明显这是一个异步调用.也就是说,在幕后,ajax 调用会触发,并且调用之后的代码不会被阻止,而是会继续执行.然后在稍后的某个不确定点,当 xhr 成功时,调用回调函数.

然后教程展示了一种不同的方法,看起来简单很多,但我不明白它是如何工作的:

$scope.twitterResult = $scope.twitter.get();

我假设 get 下面的 xhr 必须是异步的,但在这一行中,我们将 get 调用的返回值分配给一个变量,就好像它返回了同步.

我不理解这一点有错吗?这怎么可能?我认为它的工作原理非常好,我只是不明白.

我知道 get 可以返回 something 而它下面的 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).从服务器返回数据后,现有引用将填充实际数据.这是一个有用的技巧,因为通常资源被分配给一个模型,然后由视图呈现.拥有一个空对象会导致没有渲染,一旦数据从服务器到达,对象就会填充数据,并且视图会自动重新渲染以显示新数据.这意味着在大多数情况下,您永远不必为操作方法编写回调函数.

I was watching this AngularJS tutorial describing how to hook into Twitter with an Angular resource. (Video tutorial) Here is the resource that is set up in the example controller:

$scope.twitter = $resource('http://twitter.com/:action',
    {action: 'search.json', q: 'angularjs', callback: 'JSON_CALLBACK'},
    {get: {method: 'JSONP'}});

The tutorial shows that there are a couple ways to get data back from the resource using the get call. The first method is by passing a callback to the get function. The callback will be called with the result after the ajax request returns:

$scope.twitter.get(function(result) {
    console.log('This was the result:', result);
});

I understand this method. It makes perfect sense to me. The resource represents a place on the web where you can get data, and get simply makes an ajax call to a url, gets json back, and calls the callback function with the json. The result param is that json.

It makes sense to me because it seems obvious that this is an asynchronous call. That is, under the hood, the ajax call fires, and the code following the call isn't blocked, it continues to be executed. Then at some indeterminate point later on, when the xhr is successful, the callback function is called.

Then the tutorial shows a different method that looks a lot simpler, but I don't understand how it works:

$scope.twitterResult = $scope.twitter.get();

I assume that the xhr underneath get must be asynchronous, yet in this line we are assigning the return value of the get call to a variable, as if it returned synchronously.

Am I wrong for not understanding this? How is that possible? I think it's really neat that it works, I just don't get it.

I understand that get can return something while the xhr underneath it goes off and processes asynchronously, but if you follow the code example yourself, you will see that $scope.twitterResult gets the actual twitter content before any subsequent lines are executed. For example, if you write console.log($scope.twitterResult) immediately after that line, you will see the results from twitter logged in the console, not a temporary value that is replaced later on.

More importantly, because this is possible, how can I write an Angular service that takes advantage of this same functionality? Besides ajax requests, there are other types of data stores requiring asynchronous calls that can be used in JavaScript which I would love to be able to write code for synchronously in this style. For example, IndexedDB. If I could wrap my head around how Angular's built-in resources are doing it, I would give it a shot.

解决方案

$resource is not synchronous although this syntax might suggest that it is:

$scope.twitterResult = $scope.twitter.get();

What is going on here is that call to the AngularJS will, after call to twitter.get(), return immediately with the result being an empty array. Then, when the async call is finished and real data arrives from the server, the array will get updated with data. AngularJS will simply keep a reference to an array returned and will fill it in when data are available.

Here is the fragment of $resource implementation where the "magic" happens: https://github.com/angular/angular.js/blob/master/src/ngResource/resource.js#L372

This is described in the $resource documentation as well:

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. This is a useful trick since usually the resource is assigned to a model which is then rendered by the view. Having an empty object results in no rendering, once the data arrives from the server then the object is populated with the data and the view automatically re-renders itself showing the new data. This means that in most case one never has to write a callback function for the action methods.

这篇关于$resource `get` 函数如何在 AngularJS 中同步工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆