JS之封装AJAX

前端中对于ajax的使用越来越多,原生的ajax需要考虑兼容性,写法也较为复杂,所以打算自己封装一个。

原生ajax

原生ajax的使用可以分为4个步骤(3的位置不是固定的,只要在1后面即可):

  1. 新建一个XHR对象
  2. open()方法指定请求方法,请求资源和是否异步
  3. 为XHR对象绑定一个onreadystatechange函数
  4. send()发送请求

下面一一介绍:

新建XHR对象

创建XHR对象很简单,一行代码搞定:

1
var xhr = new XMLHttpRequest();

考虑要兼容IE浏览器,得像下面这样写:

1
2
3
4
5
ifwindow.XMLHttpRequest){
var xhr = new XMLHttpRequest();
}else{
var xhr = new ActiveXObject('Microsoft.XMLHTTP');
}

指定open()方法

当我们要跟服务器交互的时候,就需要像正常的http请求那样指定请求方式和请求的资源,这里XHR提供了一个open()方法,它可以接受3个参数:

1
2
3
4
open(method,url,async)
method:请求的类型,常见的有GET和POST
url:请求资源的路径
asynctrue(异步)或者false(同步)

绑定回调函数

当我们获取到资源时,我们希望能够通过回调的方式来处理它,这时就需要指定onreadystatechange方法了。在这之前,我们需要先了解两个东西,readyStatestatus

首先是redayState,它一共有5个可能的值,代表的是请求的建立成功接受响应的一系列过程:

1
2
3
4
5
0:请求未初始化
1:与服务器连接已建立
2:请求被接受
3:请求处理中
4:请求完成,且返回响应信息

每当xhr对象的readyState改变时,onreadystatechange事件就会被触发,从单词也很明显能看出了把!这样xhr请求的过程中,onreadystatechange事件就会被触发5次,一般我们只会判断readyState是否为4,因为这时候我们已经拿到了服务器的返回的信息(可能是资源也可能是其他)。

但是拿到了响应信息并不代表我们的请求就成功了,与服务器交互的结果有可能是404页面未找到,也有可能是500服务器内部错误等其他情况,这时候就需要通过另一个判断条件–status来判断了
常见的状态码有这些:

  • 200 请求成功
  • 301 永久重定向
  • 302 临时重定向
  • 304 使用缓存(条件请求If-Modified-Since)
  • 400 请求出现语法错误
  • 401 用户未认证(不能靠这个状态码来确定用户是否认证)
  • 403 资源不可用
  • 404 页面未找到
  • 500 服务器内部错误

当readyState为4且status为200时,我们就可以提取数据了,提取数据可以通过2个属性:

1
2
responseText:获得字符串形式的响应数据
responseXML: 获得XML格式的响应数据

调用send()发送请求

当我们使用post请求时,要发给服务端的数据要通过’&’连接放在send()方法里

1
xhr.send(data)

ajax封装

整合以上代码并添加一些判断以及处理函数,我们自己封装的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
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
72
73
74
75
/*
* 调用形式:
* $.ajax({
* url: '.',
* type: 'POST',
* data: {
* name: 'liby',
* height: '172'
* }
* success: function(res){
* //回调代码
* },
* fail: function(status){
* //失败的回调代码
* }
* })
*/
var $ = {
ajax: function(obj){
//处理传递过来的数据,拼接成'a=1&b=2'的形式
function formatData(obj){
var result = '';
for (var key in obj) {
result += encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]) + '&';
}
return result.slice(0,-1);
}
//如果传递进来的不是对象或者为空,直接return
if(obj == null || tpeof obj != 'object'){
return false
}
//获取传递的参数
var type = obj.type;
var url = obj.url;
var async = (obj.async == undefined || obj.async)?true:false;
var data = formatData(obj.data);
var success = obj.success || function(){};
var fail = obj.fail || function(){};
//新建xhr对象,兼容IE
ifwindow.XMLHttpRequest){
var xhr = new XMLHttpRequest();
}else{
var xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//绑定回调函数
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
var result = null;
var resultType = xhr.getResponseHeader('Content-Type');
if(resultType.indexOf("json") != -1){
result = JSON.parse(xhr.responseText);
}else if(resultType.indexOf("xml") != -1){
result = xhr.responseXML;
}else{
result = xhr.responseText;
}
success(result);
}else{
fail(xhr.status);
}
}
// 根据请求方式设置open方法和send方法,发送请求
if(type == 'get'){
url = url + '?' + data;
xhr.open(type, url, async);
xhr.send(null);
}else{
xhr.open(type, url, async);
//设置提交表单的内容类型
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(data);
}
}
}