本节课内容
AngularJs与服务器通信
主讲人介绍
沁修,葡萄藤技术总监
项目经验丰富,擅长H5移动项目开发。
专注技术选型、底层开发、最佳代码实践规范总结与推广。
直播录屏版
https://v.qq.com/x/page/o0760tr09zt.html
文字解析版
概述
请求与服务
在学习请求服务之前,我们首先来认识一下什么叫服务service。
在angualrjs中服务就是一个函数,它自己内建了有30多个服务。
常用的服务有哪些呢?
$location,
$http,
$timeout,
$interval…
有内建的服务那就有外部自定义的服务,因此其实我们也可以自己创建定制化的服务:
app.service(’str’, function() {
this.to = function(x) {
return x.toString();
}
})
创建之后,还需要在控制器里注入进去,形成依赖关系:
app.controller(‘myCtrl’, function($scope, str) {
$scope.a = str.to({a: 1})
})
$location
$location服务分析浏览器地址栏中的URL(基于window.location),让我们可以在应用中较为方便地使用URL里面的东东。
在地址栏中更改URL,会响应到 l o c a t i o n 服 务 中 , 而 在 location服务中,而在 location服务中,而在location中修改URL,也会响应到地址栏中。
所以什么时候需要用到它呢?
在应用中,任何需要对当前URL的改变作出响应,或者想去改变当前浏览器的URL的时候。
比较一下$location和window.location:
目的:
window.location和$location服务,都允许对当前浏览器的location进行读写访问。
API:
window.location暴露一个未经加工的对象,附带一些可以直接修改的属性;
而$location服务则是暴露一些jQuery风格的getter/setter方法。
与angular应用生命周期的整合:
l o c a t i o n 知 道 关 于 所 有 内 部 生 命 周 期 的 阶 段 , 与 location知道关于所有内部生命周期的阶段,与 location知道关于所有内部生命周期的阶段,与watch等整合;
而window.location则不行。
它不能做的事?
有,当浏览器URL改变的时候,不会导致页面重新加载(page reload)。
如果需要做这件事情(更改地址,实现page reload),请使用较低级别的API,window.location.href。
$http
$http服务就是读取远程服务器的数据的核心服务。
它是对原生XMLHttpRequest对象的简单封装,是只能接受一个参数的方法。
$http({
url:url, //绝对或者相对的URL路径,请求的目标
method:method, //表示发送的请求类型 GET/DELETE/HEAD/JSONP/POST/PUT
params:params , //字符串或对象。会被转化成查询字符串加到URL后面,如果不是字符串会被JSON序列化转为?param1=xx1&m2=xx2的形式
data: data //字符串或者对象。包含了将被当做消息体发送给服务器的数据,通常在POST请求时使用
// 其他常用参数
// headers 对象
在我们做POST和后台配合的时候会用到headers,其代表随请求发送的HTTP头字符串
// transformRequest 函数或函数组
用来对HTTP请求头和体信息进行转换,并返回转化后的版本,通常用于在请求发送给服务器之前对其序列化
// transformResponse 函数或函数组
用来HTTP响应头和响应体信息进行转换,并返回转化后的版本,通常用来反序列化
// cache 布尔值或对象。
默认情况下, h t t p 服 务 不 会 对 请 求 进 行 本 地 缓 存 , 可 通 过 向 http服务不会对请求进行本地缓存,可通过向 http服务不会对请求进行本地缓存,可通过向http请求传递一个布尔参数来启用缓存。
这样在第一次请求时,http服务会向服务器发送一个请求,在第二次发送同一个请求时,会从缓存中取回请求的结果。
另外还可以为cache传入一个自定义的缓存实例来代替布尔值。
// timout 数值或者promise对象
如果为数值那么请求会在指定的毫秒后结束(会跳到失败的error方法里) ,如果为对象那么promise对象在被resolve时请求会被中止,方法执行完毕再执行请求
// responseType 字符串
该选项会在请求中设置XMLHttpResponseType属性有以下类型:
“”字符串默认,
”arraybuffer”(arraybuffer),
”blob”(blob对象),
“document”(HTTP文档),
”json“(从JSON对象解析出来的json字符串),
”text“(字符串),
”moz-blob“(Firefox的接收进度事件),
”moz-chunked-text“(文本流),
”moz-chunked-arraybuffer”(arraybuffer流)
})
.then()
这个方法会返回一个promise对象,具有sccess和error两个方法。
$http({
url:url, //请求的url路径
method:method, //GET/DELETE/HEAD/JSONP/POST/PUT
params:params , //转为 ?param1=xx1¶m2=xx2的形式
data: data //包含了将被当做消息体发送给服务器的数据,通常在POST请求时使用
}).success(response, status, header, config, statusText){
// 响应成功时调用
}).error(res) {
// 响应失败时调用
})
当然我们也可以在相应返回时直接使用then函数来处理回调
$http({
url:url, //请求的url路径
method:method, //GET/DELETE/HEAD/JSONP/POST/PUT
params:params , //转为 ?param1=xx1¶m2=xx2的形式
data: data //包含了将被当做消息体发送给服务器的数据,通常在POST请求时使用
})
.then(function (res){
// res响应对象包含5个属性,和前面说到的success是等价的。
// 1. data(字符串或对象):响应体,就是后台返回的数据
// 2. status:相应http的状态码,如200
// 3. headers(函数):头信息的getter函数,可以接受一个参数,用来获取对应名字的值
// 4. config(对象):生成原始请求的完整设置对象
// 5. statusText:相应的http状态文本,如”ok"
})
then方法和success方法的主要区别就是,then方法会接受到完整的响应对象,而success则会对响应对象进行析构。
$http服务的快捷方法
$http提供了一些快捷方法让我们使用,一共有六个(其实是六种请求模式)
1、$http.get(url字符串,config可选的配置-对象类型) 返回HttpPromise对象
2、$http.delete(url字符串,config可选的配置-对象类型) 返回HttpPromise对象
3、$http.head(url字符串,config可选的配置-对象类型) 返回HttpPromise对象
4、$http.jsonp(url字符串,config可选的配置-对象类型) 返回HttpPromise对象
5、$http.post(url字符串,data对象或字符串,config可选的配置-对象类型) 返回HttpPromise对象
6、$http.put(url字符串,data对象或字符串,config可选的配置-对象类型) 返回HttpPromise对象
提交表单的问题
到这里大家应该都会用$http服务来与服务器通信了
但大家在开发的时候遇到post请求提交form表单数据的时候,很可能会遇到这个问题:
后端获取不到前端提交的数据。
其原因是这样的:
$http的post方法预设的content-type头是”application/json;charset=utf-8”
然后不会对数据做序列化处理,这样提交的数据格式就对不上号,让后端抓不到。
因此我们需要先对数据进行序列化处理,比如用jquery的$.param方法。
当然也可以自己尝试去写一个方法来将对象序列化
$http({
method: “POST”,
url: “xxx”,
headers: {‘Content-Type’: ‘application/x-www-form-urlencoded’},
data: $.param({a:1, b:1})
}).then()
自己来序列化:
var app = angular.module(“app", function($httpProvider) {
// Use x-www-form-urlencoded Content-Type
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
/**
* The workhorse; converts an object to x-www-form-urlencoded serialization.
* @param {Object} obj
* @return {String}
*/
var param = function(obj) {
var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
for(name in obj) {
value = obj[name];
if(value instanceof Array) {
for(i=0; i
});
Content-Type说明:
application/x-www-form-urlencoded
主要向服务器提交用户隐私相关的信息,浏览器支持
multipart/form-data
向服务器上传小文件,浏览器支持
application/json
向后台服务器提交结构化数据,RESTful 设计风格需要
text/xml
向后台服务器提交结构化数据,RESTful 设计风格需要
上传图片的问题
现在我们对于处理普通的通信应该没什么问题了,但有没有想过上传文件上传图片应该怎么办?
过去的图片上传都需要写一个表单直接刷新提交到服务器,但使用异步通信的方式呢?
实际上现在我们只需要做三件事:
1.把文件二进制化
2.使用FormData对象,将数据作为参数放到这个对象中
3.异步提交这个对象
$scope.upload = function(files) {
$scope.reader = new FileReader(); //创建一个FileReader接口
$scope.reader.readAsDataURL(files[0]); //FileReader的方法,把图片转成base64
var data = new FormData(); //以下为像后台提交图片数据
data.append('image', files[0]);
$http({
method: 'post',
url: '',
data: data,
headers: {'Content-Type': undefined},
transformRequest: angular.identity
}).success(function(data) {
})
}
contentType这里设置成了undefined
主要是因为AngularJS本身其实是默认上传的是JSON格式的(application/JSON)。
如果我们将其设置成undefined,则可以保证在data转成formData之前被识别,而之后其实Angular会帮我们自动识别的。
以上就是上节课的内容解析啦,
以上就是上节课的内容解析啦
“我们相信人人都可以成为一个工程师,现在开始,找个师兄,带你入门,学习的路上不再迷茫。
技能树.IT修真院
下节预告:
微信小程序入门
讲解什么是小程序,以及开发一个小程序都需要做什么准备
随后进行一个小程序的开发实践演示