前端网络请求的前世今生

前言

在差不多2个月前的之前的时间,我一直认为前端的请求就是httpPackage.gethttpPackage.post,ajax听说过,但是没写过,所以不是特别清楚,后来开始复习的时候,看《Javascript高级程序设计》时,才慢慢了解ajax以及ajax的处理流程,但还是那句话,很少写所以印象不是特别深。所以当时一个面试官问我网络请求怎么写,我回答说我们项目在postget方法上做进一步封装时,他就开始揪着我问ajax,可能是比较看重的是基础。当时的回答现在想想不是很满意,我说大概就是新建一个XMLHttpRequest对象,然后调用open、send方法。

今天好好总结一些原生ajax,jquery中的$ajax以及框架http包中的网络请求方法之间的联系。

Ajax

Ajax = Asynchronous JavaScript + XML。Ajax能够向服务器请求额外的数据而无需卸载页面,可以带来更好的用户体验。

XMLHttpRequest对象

Ajax的核心是XMLHttpRequest对象,简称XHR。XHR为向服务器发送请求和解析服务器响应提供了流畅的接口,能够以异步方式从服务器获取更多信息,意味着用户点击后,可以不必刷新页面也能取得新数据。也就是说,可以通过XHR对象取得新数据,然后通过DOM将新数据插到页面中。另外,虽然名字中包含XML的成分,但Ajax通信与数据格式无关,这种技术就是无需刷新页面即可从服务器取得数据,但不一定是XML数据。

​ ——《javascript高级程序设计》

XHR的用法

创建XHR对象
1
var xhr = createXHR();

若要兼容老版的IE浏览器,则可以使用 ActiveX 对象:

1
2
3
4
5
6
7
8
9
10
11
12
var xhr;
if (window.XMLHttpRequest) { // Mozilla, Safari...
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
xhr = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {}
}
}
调用open()
1
2
3
4
5
xhr.open('method','url',isAsynchronous);

//method: ajax请求方法名,get、post、delete等
//url: ajax请求的url
//isAsynchronous: boolean,表示是否异步发送此请求

调用open()方法并不会真正发送请求,而只是一个请求以备发送。

调用send()
1
2
3
xhr.send(null);

//send接受一个参数,即要作为请求主体发送的数据。如果不需要通过请求主体发送数据,则必须传入null,因为这个参数对有些浏览器来说是必须的。

调用send()以后,请求就会被分派到服务器。

同步ajax请求

1
2
3
4
5
6
7
8
9
10
11
12
13
var xhr = createXHR();
xhr.open('method','url',false);
//自定义头部信息
//xhr.setRequestHeader("myHeader","header");
xhr.send(null);

//同步等待请求返回,执行数据处理函数
//200 表成功,responseText中的数据就绪,304表示请求的资源并没有被修改,可直接使用
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
}else{
alert("Request fail: " + xhr.status);
}

XHR对象的相关响应属性如下:

属性 简介
responseText 作为响应主体被返回的文本
responseXML 保存包含着响应数据的XML DOM文档(若存在,否则为null)
status 响应HTTP状态
statusText HTTP状态说明

异步ajax请求

异步请求,可以使javascript继续执行而不需要等待响应。可以检测XHR对象的readyState属性,该属性表示请求/相应过程的当前活动阶段。这个值每改变一次就触发一次readystatechange事件。这个属性可取值如下:

属性值 说明
0 尚未初始化。尚未调用open()方法
1 启动。已经调用open()方法,但尚未调用send()方法
2 发送。已经调用send()方法,但尚未收到相应
3 接收。已经接收到部分响应数据
4 完成。接收到全部数据,并且可以在客户端使用该数据了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var xhr = createXHR();

xhr.onreadystatechange = function(){
if(xhr.readyState == 0){
//todo loading
}
if (xhr.readyState == 4){
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
//todo close loading
}
};
xhr.open('method','url',true);
//自定义头部信息
//xhr.setRequestHeader("myHeader","header");
xhr.send(null);

//取消异步请求
//xhr.abort();

以上,就是关于原生ajax请求的简介,至于请求方法,交互数据,交互过程http字段的变化,如果想详细说,那么又是3篇长文了。。

jquery中的$ajax

先来看下jquery中的ajax请求怎么写。

1
2
3
4
5
6
7
8
$.ajax({
url: 'url',
type: 'method'
}).done(function(res){
console.log(res);
}).fail(function(){
console.log("Error: " + err.status);
})

jquery中的ajax请求实际上是对原生的请求进行的一次封装,包括现在很多http的包,都是对原生ajax请求的封装(有点废话)。

优点

首先就是使用简洁、方便。

其次,帮我们解决了浏览器的兼容问题,在任何浏览器下正常情况下都可以直接使用。

看源码:

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
// Functions to create xhrs
function createStandardXHR() {
try {
return new window.XMLHttpRequest();
} catch( e ) {}
}

//适用IE7之前的版本
function createActiveXHR() {
try {
return new window.ActiveXObject("Microsoft.XMLHTTP");
} catch( e ) {}
}

// Create the request object
// (This is still attached to ajaxSettings for backward compatibility)
jQuery.ajaxSettings.xhr = window.ActiveXObject ?
/* Microsoft failed to properly
* implement the XMLHttpRequest in IE7 (can't request local files),
* so we use the ActiveXObject when it is available
* Additionally XMLHttpRequest can be disabled in IE7/IE8 so
* we need a fallback.
*/
function() {
return !this.isLocal && createStandardXHR() || createActiveXHR();
} :
// For all other browsers, use the standard XMLHttpRequest object
createStandardXHR;

再粗略看了一下,内部也是open,send。

jQuery中的全局ajax事件

  • ajaxComplete()
  • ajaxError()
  • ajaxSend()
  • ajaxStart()
  • ajaxStop()
  • ajaxSuccess()

框架(NG2+)中的网络请求

在封装的时候也是做了浏览器的兼容处理。找了好久才找到。这个处理是在rxjs这个包里面处理的。。其他的有兴趣自己去找吧。。溜了溜了。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function getXMLHttpRequest(): XMLHttpRequest {
if (root.XMLHttpRequest) {
return new root.XMLHttpRequest();
} else {
let progId: string;
try {
const progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
for (let i = 0; i < 3; i++) {
try {
progId = progIds[i];
if (new root.ActiveXObject(progId)) {
break;
}
} catch (e) {
//suppress exceptions
}
}
return new root.ActiveXObject(progId);
} catch (e) {
throw new Error('XMLHttpRequest is not supported by your browser');
}
}
}

总结

关于框架里面的ajax请求写得比较少,因为要看懂源码才能比较优劣啊摔。。目前只知道封装了原生的ajax请求而已。。总之还是先好好学基础。。

还有就是学习前端最好还是不要一开始就入框架,想直接用框架的话最好还是用以js为主语的框架,最好别一开始就使用ng2+,个人建议。。

greylag-goose-2139296_960_720.jpg