从零学前端第十六讲:AngularJs与服务器通信

本节课内容

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服务中,而在 locationlocation中修改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知道关于所有内部生命周期的阶段,与 locationwatch等整合;

而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服务不会对请求进行本地缓存,可通过向 httphttp请求传递一个布尔参数来启用缓存。

这样在第一次请求时,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修真院

下节预告:

微信小程序入门

讲解什么是小程序,以及开发一个小程序都需要做什么准备

随后进行一个小程序的开发实践演示

你可能感兴趣的:(从零开始学前端)