在AngularJS入门教程中详细解释XHR和依赖注入
到目前为止,我们已经使用了三个硬编码的手机记录数据集。现在我们使用内置服务AngularJS $ http来获取更大的手机记录数据集。我们将使用AngularJS的依赖注入(DI)功能为PhoneListCtrl控制器提供这个AngularJS服务。
请重置工作目录:
git结账-f步骤-5
刷新浏览器,现在应该看到20部手机的列表。
下面列出了步骤4和步骤5之间最重要的区别。你可以在GitHub中看到完全的不同。
数据
您项目中的app/phones/phones.json文件是一个数据集,它以json格式存储了更大的手机列表。
以下是该文件的示例:
[ { 'age': 13,' id ' : ' Motorola-default-wit-moto blur ',' name': '摩托罗拉default \ u 2122 wit moto blur \ u 2122 ',' snippet': '生活抛给你的一切你都准备好了吗'.},]控制器
我们在控制器中使用AngularJS服务$HTTP向你的Web服务器发送一个HTTP请求,从而从app/phones/phones.json文件中获取数据。$http只是AngularJS的许多内置服务之一,它可以处理Web应用程序的一些常规操作。AngularJS可以在您需要的任何地方注入这些服务。
服务通过AngularJS的依赖注入DI子系统来管理。依赖注入服务可以让你的Web应用很好的构造(比如分离表示层、数据和控制的组件)和松散耦合(一个组件本身不需要解决组件之间的依赖问题,都由DI子系统处理)。
app/js/controller . js
function PhoneListCtrl($scope,$ http){ $ http . get(' phones/phones . JSON ')。success(function(data){ $ scope . phones=data;});$ scope.orderProp=' age}$http发送一个HTTP GET请求到phone/phones.json的Web服务器(注意url是相对于我们的index.html文件的)。服务器用json文件中的数据进行响应。(该响应可以从后端服务器实时动态生成。但是对于浏览器来说,它们看起来都一样。为了简单起见,我们在教程中简单地使用一个json文件。)
$http服务返回[对象响应][ng。$q]获得成功。当异步响应到达时,这个对象响应函数用于处理服务器响应的数据,并将数据分配给作用域的电话数据模型。请注意,AngularJS将自动检测这个json响应,并为我们解决它!
为了使用AngularJS服务,您只需要在控制器的构造函数中将所需服务的名称声明为参数,如下所示:
函数PhoneListCtrl($scope,$ http){ 0.}
当构造控制器时,AngularJS的依赖注入器会将这些服务注入到您的控制器中。当然,依赖注入器也处理可能存在于所需服务中的任何可传递的依赖(一个服务通常依赖于其他服务)。
注意参数名称很重要,因为注射器将使用它们来找到相应的依赖项。
“$”前缀命名约定
您可以创建自己的服务。事实上,我们将在第11步中学习它。作为一种命名约定,AngularJS内置服务、作用域方法和一些其他的AngularJS API都在它们的名称前面使用了一个“$”前缀。不要使用前缀“$”来命名您自己的服务和模型,否则您可能会有名称冲突。
关于JS压缩
AngularJS通过控制器构造函数的参数名推断依赖的服务名。因此,如果要压缩PhoneListCtrl控制器的JS代码,它的所有参数都会被同时压缩。此时,无法根据注射系统正确识别服务。
为了克服压缩带来的问题,只需将一个依赖于服务标识符的数组分配给controller函数中的$inject属性,就像段落的最后一行被注释掉一样:
PhoneListCtrl。$inject=['$scope ',' $ http '];
还可以使用另一种方法来指定依赖项列表并避免压缩问题。——使用Javascript数组构造控制器:把要注入的服务放入字符串数组(表示依赖项的名称),数组的最后一个元素是控制器的方法函数:
var PhoneListCtrl=['$scope ',' $http ',function($scope,$http) { /*构造函数体*/}];
上面提到的两种方法可以完美地与AngularJS可以注入的任何函数一起工作。选择哪种方法完全取决于项目的编程风格。建议使用数组方法。
试验
测试/单元/控制器pec.js:
因为我们现在使用依赖注入,并且我们的控制器包含许多依赖服务,所以为我们的控制器构建测试有点复杂。我们需要使用新的操作,并为构造函数提供一些伪实现,包括$http。然而,我们推荐的方法(也更简单)是在测试环境中创建一个控制器,在以下场景中使用与AngularJS相同的方法:
description(' PhoneCat controllers ',function(){ description(' PhoneListCTRL ',function(){ var scope,Ctrl,$ httpBackendbeforeHeaLTH(inject(function(_ $ Httpbackend _,$rootScope,$ controller){ $ Httpbackend=_ $ Httpbackend _;$ Httpbackend . expect get(' phones/phones . JSON ')。响应([{name: 'Nexus S'},{ name : ' Motorola DROID ' }]);作用域=$rootScope。$ new();ctrl=$controller(PhoneListCtrl,{ $ scope : scope });}));注意:因为我们在测试环境中加载了Jasmine和angular-mock.js,所以我们有两个辅助方法,module和inject,来帮助我们获取和配置注入器。
通过以下方式,我们在测试环境中创建了一个控制器:
我们使用inject方法将$rootScope、$controller和$ httpBackend服务实例注入Jasmine的beforeEach函数。这些实例都来自一个注射器,但这个注射器将在每次测试中重新创建。这确保了每个测试都从一个众所周知的起点开始,并且每个测试都独立于其他测试。
调用$rootScope。$new()为我们的控制器创建一个新的范围。
PhoneListCtrl函数和新创建的作用域作为参数传递给注入的$controller函数。
由于我们当前的代码在创建PhoneListCtrl子范围之前使用$http服务来获取控制器中的电话列表数据,因此我们需要告诉测试套件等待来自控制器的请求。我们可以做到这一点:
将请求服务$httpBackend注入到我们的beforeEach函数中。这是该服务的假版本,它有助于在生产环境中处理所有XHR和JSONP请求。该服务的伪版本允许您在不考虑本机API和全局状态——的情况下编写测试,这可能会构成测试的噩梦。
使用$HTTPBackend.expectGET方法告诉$HTTPBackend服务等待一个http请求,并告诉它如何响应它。请注意,在我们调用$httpBackend.flush方法之前,不会发送响应。
现在
it('应该用从xhr ' function(){ expect(scope . phones)获取的2个电话创建' phones '模型。tobe undefined();$ Httpbackend . flush();期待(scope.phones)。toeqal([{ name : ' Nexus S ' },{ name : ' Motorola DROID ' }]);});在浏览器中,我们调用$httpBackend.flush()来刷新请求队列。这将使$http服务返回的承诺(请参见此处了解什么是承诺)被解释为规范响应。
我们设置了一些断言来验证手机数据模型已经在范围内。
最后,我们验证orderProp的默认值是否设置正确:
它('应该设置orderProp模型的默认值',function(){ expect(scope . order prop))。toBe(' age ');});练习
在index.html末尾添加一个{{phones | json}}绑定,观察json格式的手机列表。
在PhoneListCtrl控制器中,对HTTP响应进行预处理,使得只显示前五个手机列表。在$http回调函数中使用以下代码:
$scope.phones=data.splice(0,5);
摘要
现在您应该感受到使用AngularJS服务是多么容易了(感谢AngularJS服务的依赖注入机制)。转到第6步,您将向手机添加缩略图和链接。
感谢您对本网站的支持,并继续更新相关文章!
版权声明:在AngularJS入门教程中详细解释XHR和依赖注入是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。