全面解析前端网络请求方式

关于Ajax及其出现前后的影响

Ajax的全称是Asynchronous JavaScript and XML 中文名称定义为异步的JavaScript和XML(但由于JSON的许多优势,目前JSON的使用比XML更加普遍)。Ajax是Web2.0技术的核心由多种技术集合而成,使用Ajax技术不必刷新整个页面,只需对页面的局部进行更新,可以节省网络带宽,提高页面的加载速度,从而缩短用户等待时间,改善用户体验.
传统的web应用,当我们提交一个表单请求给服务器,服务器接收到请求之后,返回一个新的页面给浏览器,这种做法浪费了很多带宽.
Ajax的核心是XMLHttpRequest 是支持异步请求的技术,可以发送请求给服务器,并且不阻塞用户

总结:只要是JS调用异步通讯组件并使用格式化的数据来更新web页面上的内容或操作过程,那么我们用的方法就可算是AJAX。

常见网络请求方式

  • form,iframe
  • xhr(浏览器内置api)
  • jq-ajax(基于xhr封装)
  • fetch(浏览器内置api,基于promise)
  • axios(基于xhr封装)
form

form 表单提交后进行后台处理程序,没有直接返回值,只能进行后台处理,相当于放弃当前页面,后端返回新页面

xhr
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
var xhr = new XMLHttpRequest();

// 接收返回值
xhr.onreadystatechange = function(){ // 可以监听到其状态为2(请求已接收),状态为3(请求处理中),状态为4(请求处理完成,响应就绪)。
if(xhr.readyState === 4 ){
if(xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
console.log(xhr.responseText);
}
}
}

// 处理请求参数
postData = {"name1":"value1","name2":"value2"};
postData = (function(value){
var dataString = "";
for(var key in value){
dataString += key+"="+value[key]+"&";
};
return dataString;
}(postData));

// 设置请求头
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");

// 异常处理
xhr.onerror = function() {
console.log('Network request failed')
}

// 跨域携带cookie
xhr.withCredentials = true;

// 初始化请求
xhr.open('post','www.xxx.com',true)

// 发出请求
xhr.send(postData);

// 终止请求,调用此方法后readyState将被设置为0,不会触发onreadystatechange
xhr.abort()

jq-ajax
1
2
3
4
5
6
7
8
9
10
11
12
13
$.ajax({
dataType: 'json', // 设置返回值类型
contentType: 'application/json', // 设置参数类型
headers: {'Content-Type','application/json'},// 设置请求头
xhrFields: { withCredentials: true }, // 跨域携带cookie
data: JSON.stringify({a: [{b:1, a:1}]}), // 传递参数
error:function(xhr,status){ // 错误处理
console.log(xhr,status);
},
success: function (data,status) { // 获取结果
console.log(data,status);
}
})

fetch

Fetch API是一个用于访问和操纵HTTP管道的强大的原生 API。更底层的api,兼容支持差

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const options = {
method: "POST", // 请求参数
headers: { "Content-Type": "application/json"}, // 设置请求头
body: JSON.stringify({name:'123'}), // 请求参数
credentials: "same-origin", // cookie设置
mode: "cors", // 跨域
}
fetch('http://www.xxx.com',options)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson); // 响应数据
})
.catch(function(err){
console.log(err); // 异常处理
})

fetch缺点

  • 不能直接传递JavaScript对象作为参数
  • 需要自己判断返回值类型,并执行响应获取返回值的方法
  • 获取返回值方法只能调用一次,不能多次调用
  • 无法正常的捕获异常
  • 老版浏览器不会默认携带cookie
  • 不支持jsonp

可以对其进行封装,解决部分问题

axios

它本身也是对原生XHR的封装。 - 支持node,创建http请求 - 支持Promise API - 客户端防止CSRF:每个请求带一个cookie拿到的key - 拦截请求和响应 - 可取消请求

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
axios({
method: 'GET',
url: url,
})
.then(res => {console.log(res)})
.catch(err => {console.log(err)})

// get请求
axios.get(url)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});

// post请求
axios.post(‘/user’, {
name: 'Jerry',
lastName: 'Liang'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});

书写相对优雅,面对一些特殊情况(多请求串,并行)也有不错的可读性和处理方式

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// 串行
// ajax
$.ajax({
url: '',
data: '',
success: function (data) {
$.ajax({
url: '',
data: '',
success: function (data) {
$.ajax({
// 如此一层嵌套一层
})
}
})
}
})

//axios
axios.get(url)
.then(res => {
return axios.get(url,{
{name:result.name}
});
}).then(res => {
//如此一层层嵌套
});

// 并行
//ajax 通过计数器实现(虽然Jquery支持$.when的方式,但此处不做案例)
var num = 0;
function all(){
num++;
if(n>=3)console.log('三个请求全部完成');
}
$.ajax({
url: '',
data: '',
success: function (data) {
console.log("ajax请求1 完成");
all();
}
})
$.ajax({
url: '',
data: '',
success: function (data) {
console.log("ajax请求2 完成");
all();
}
})
$.ajax({
url: '',
data: '',
success: function (data) {
console.log("ajax请求3 完成");
all();
}
})

//axios
function getInfo() {
return axios.get(url);
}
function getUser() {
return axios.get(url);
}
axios.all([getInfo(), getUser()])
.then(axios.spread(function (info, user) {
// 两个请求现在都执行完成
}));

参考:

全面分析前端的网络请求方式
【研究与总结】关于前端请求的那些事(xhr/ajax/fetch/axios)