简介
Web前后端中数据交互是实际项目业务中最为常见的一种需求。目前比较成熟的解决方案是采用axios的方式,而其本质也就是计算机网络中的HTTP的概念。
HTTP简介
HTTP(hypertext transport protocol)协议,即超文本传输协议,详细规定了浏览器和万维网服务器之间互相通信的规则和约定。
其用于数据交互的两个重要概念为:HTTP请求报文和HTTP响应报文。
HTTP请求报文
一个HTTP请求报文由请求行request line、请求头部header、空行和请求数据4个部分组成。
请求行
请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号:分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:
User-Agent:产生请求的浏览器类型。
Accept:客户端可识别的内容类型列表。
Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
请求头部
请求头部由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。例如,GET /index.html HTTP/1.1。
HTTP协议的请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。
其中最常见的为GET(查询)和POST(增加)请求。(PUT请求对应于更新,DELETE请求对应于删除)
GET请求
GET方法要求服务器将URL定位的资源放在响应报文的数据部分,回送给客户端。使用GET方法时,请求参数和对应的值附加在URL后面,利用一个问号(?)代表URL的结尾与请求参数的开始,传递参数长度受限制。
如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。POST请求
POST方法将请求参数封装在HTTP请求数据中,以名称/值的形式出现,可以传输大量数据,这样POST方式对传送的数据大小没有限制,而且也不会显示在URL中。
空行
最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
请求数据
请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type和Content-Length。
HTT响应报文
和请求报文类似,HTTP响应报文也由三个部分组成,分别是:状态行、消息报头、响应正文。
在响应报文中唯一真正的区别在于第一行中用状态信息代替了请求信息。状态行status line通过提供一个状态码来说明所请求的资源情况。
状态行格式
HTTP-Version Status-Code Reason-Phrase CRLF
其中,HTTP-Version表示服务器HTTP协议的版本;Status-Code表示服务器发回的响应状态代码;Reason-Phrase表示状态代码的文本描述。状态代码由三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。
1xx:指示信息—表示请求已接收,继续处理。2xx:成功—表示请求已被成功接收、理解、接受。3xx:重定向—要完成请求必须进行更进一步的操作。4xx:客户端错误—请求有语法错误或请求无法实现。5xx:服务器端错误—服务器未能实现合法的请求。
常见状态代码、状态描述的说明如下。
200 OK:客户端请求成功。400 Bad Request:客户端请求有语法错误,不能被服务器所理解。401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用。403 Forbidden:服务器收到请求,但是拒绝提供服务。404 Not Found:请求资源不存在,举个例子:输入了错误的URL。500 Internal Server Error:服务器发生不可预期的错误。503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常。
参考博客
Ajax简介
AJAX全称为Asynchronous JavaScript And XML,就是异步的JS和XML。AJAX不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。它是一种技术方案,但并不是一种新技术。
它依赖的是现有的CSS/HTML/Javascript,而其中最核心的依赖是浏览器提供的XMLHttpRequest对象。这个对象为向服务器发送请求和解析服务器响应提供了流畅的接口,使得浏览器可以发出HTTP请求与接收HTTP响应,实现在页面不刷新的情况下和服务端进行数据交互。
本质上就是一种依赖于HTTP技术提出的一种解决Web数据交互的解决方案。
通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势为无刷新获取数据。
原生Ajax实现
本质上就是对浏览器提供的XMLHttpRequest类进行一系列的操作。
请求状态
0:请求未初始化,还没有调用open()
1:请求已经建立,但是还没有发送,还没有调用send()
2:请求已发送,正在处理中,通常现在可以从响应中获取内容头。
3:请求在处理中;通常响应中已有部分数据可用了,没有全部完成。
4:响应已完成;可以获取并使用服务器的响应了。
简单使用
1 | // 1.创建 XMLHttpRequest 对象 |
请求超时与网络异常处理
1 | const xhr = new XMLHttpRequest(); |
取消请求
1 | xhr.abort(); |
常见的Ajax请求方式
jQuery
1 | $.ajax({ |
Axios
1 | axios.defaults.baseURL = 'http://127.0.0.1:8000'; |
Fetch
1 | fetch('http://127.0.0.1:8000/fetch-server?vip=10', { |
跨域问题
跨越原因
一个网页向另一个不同域名/不同协议/不同端口的网页请求资源,这就是跨域。
跨域原因产生:在当前域名请求网站中,默认不允许通过ajax请求发送其他域名。因为浏览器使用了同源策略。
同源策略
同源策略是Netscape提出的一个著名的安全策略,现在所有支持JavaScript的浏览器都会使用这个策略。同源策略是浏览器最核心也最基本的安全功能,如果缺少同源策略,浏览器的正常功能可能受到影响。可以说web是构建在同源策略的基础之上的,浏览器只是针对同源策略的一种实现。
同源:协议、域名、端口号必须完全相同。违背同源策略就是跨域。
浏览器使用同源策略是为了保证用户的信息安全,防止恶意网站窃取数据,如果网页之间不满足同源要求,将不能:
- 共享
Cookie、LocalStorage、IndexDB - 获取
DOM AJAX请求不能发送
解决方案
- 前端使用
jsonp(不推荐使用) - 后台
Http请求转发 - 后台配置同源
Cors(推荐) - 使用
SpringCloud网关 - 使用
nginx做转发 (推荐)
Axios简介
目前前端最流行的ajax请求库。react/vue官方都推荐使用axios发送ajax请求。其特点主要包括:
- 基于
xhr(XMLHttpRequest) + promise的异步ajax请求库 - 浏览器端/
node端都可以使用 - 支持请求/响应拦截器
- 支持请求取消
- 请求/响应数据转换
- 批量发送多个请求
创建实例
1 | const axios1 = axios.create({ |
调用顺序
调用axios()并不是立即发送ajax请求, 而是需要经历一个较长的流程:
请求拦截器2 => 请求拦截器1 => 发送ajax请求 => 响应拦截器1 => 响应拦截器2 => 请求的回调(如果此时有多个请求和响应拦截器)
此流程是通过promise串连起来的, 请求拦截器传递的是 config, 响应拦截器传递的是response。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49// 设置请求拦截器 config 配置对象
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功 - 1号');
//修改 config 中的参数
config.params = {
a: 100
};
return config;
}, function (error) {
console.log('请求拦截器 失败 - 1号');
return Promise.reject(error);
});
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功 - 2号');
//修改 config 中的参数
config.timeout = 2000;
return config;
}, function (error) {
console.log('请求拦截器 失败 - 2号');
return Promise.reject(error);
});
// 设置响应拦截器
axios.interceptors.response.use(function (response) {
console.log('响应拦截器 成功 1号');
return response.data;
// return response;
}, function (error) {
console.log('响应拦截器 失败 1号')
return Promise.reject(error);
});
axios.interceptors.response.use(function (response) {
console.log('响应拦截器 成功 2号')
return response;
}, function (error) {
console.log('响应拦截器 失败 2号')
return Promise.reject(error);
});
//发送请求
axios({
method: 'GET',
url: 'http://localhost:3000/posts'
}).then(response => {
console.log('自定义回调处理成功的结果');
console.log(response);
});
默认配置
1 | // 默认配置 |
其他
请求/相应数据转换器
1 | // 请求转换器: 对请求头和请求体数据进行特定处理的函数 |
response与error的整体结构
1 | // response的整体结构 |
ajax fetch和axios的区别
ajax
本身是针对MVC的编程,不符合现在前端MVVM的浪潮基于原生的XHR开发,XHR本身的架构不够清晰,已经有了fetch的替代方案。
fetch
fetch号称是AJAX的替代品,是在ES6出现的,使用了ES6中Promise对象。
fetch的代码结构比ajax简单多了,但fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。
优点
- 符合关注分离: 没有将输入、输出和用事件来跟踪的状态混杂在一个对象里。
- 更加底层,提供的
API丰富,是更好更方便的写法。 - 脱离了
XHR,是ES规范里新的实现方式。
缺点
fetch只对网络请求报错,对400、500都当成成功的请求,需要封装去处理。fetch默认不会带cookie,需要添加配置项。fetch不支持abort(中止) 、不支持超时控制,使用setTimeout及Promise.reject实现的超时控制并不能阻止请求过程继续在后台运行,造成了量的浪费。fetch不能原生检测请求的进度,而XHR可以。
axios
Axios是一个基于promise的HTTP库,可以在浏览器和Nodejs中使用。
特性
- 从浏览器中创建
XMLHttpRequests - 从
Node.js中创建http请求 - 支持
Promise API - 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换
JSON数据 - 客户端支持防御
XSRF