Ajax

  • XMLHttpRequest对象 | ActiveX对象
    • Js引擎内置的构造函数
    • var xhr = new XMLHttpRuquest()
    • 兼容性:IE5/IE6试用ActiveX对象
    • var xhr = new ActiveXObject(‘Microsoft.XMLHTTP’)
    • onreadystatechange事件:挂载到XMLHttpRequest对象上的事件
    • readyState状态:通过XMLHttpRequest对象发送HTTP请求的各阶段状态码
    • status:服务器响应的状态码
  • 当readyState变化时,将触发onreadystatechange事件执行其回调函数
    • 0:请求未初始化
    • 1:服务器建立已连接
    • 2:请求已接收
    • 3:请求处理中
    • 4:请求已完成,且响应已就绪
    • readyState仅仅是针对请求的状态码,获取资源是否成功取决于status的状态
  • xhr.setRequestHeader(“Content-type”,"application/x-www-form-unlencoded’)
    • POST请求方式必须设置这个请求头信息,目的是请求体中的数据转换位键值对
  • 原生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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
var xhr = (function(){

function _doAjax(opt){
var o = window.XMLHttpRequest ?
new XMLHttpRequest() :
new ActiveXObject('Microsoft.XMLHTTP');

if(!o){
throw new Error('您的浏览器不支持异步发起HTTP请求');
}

var opt = opt || {},
type = (opt.type || 'GET').toUpperCase(),
async = '' + opt.async === 'false' ? false : true,
dataType = opt.dataType || 'JSON',
jsonp = opt.jsonp || 'cb',
jsonpCallback = opt.jsonpCallback || 'jQuery' + randomNum() + '_' + new Date().getTime();
url = opt.url,
data = opt.data || null,
timeout = opt.timeout || 30000,
error = opt.error || function(){},
success = opt.success || function(){},
complete = opt.complete || function(){},
t = null;

if(!url){
throw new Error('您没有填写URL');
}

if(dataType.toUpperCase() === 'JSONP' && type !== 'GET'){
throw new Error('如果dataType为JSONP,type请您设置GET或不设置');
}

if(dataType.toUpperCase() === 'JSONP'){
var oScript = document.createElement('script');
oScript.src = url.indexOf('?') === -1
? url + '?' + jsonp + '=' + jsonpCallback
: url + '&' + jsonp + '=' + jsonpCallback;
document.body.appendChild(oScript);
document.body.removeChild(oScript);
window[jsonpCallback] = function(data){
success(data);
};
return;
}

o.onreadystatechange = function(){
if(o.readyState === 4){
if((o.status >= 200 && o.status < 300) || o.status === 304){
switch(dataType.toUpperCase()){
case 'JSON':
success(JSON.parse(o.responseText));
break;
case 'TEXT':
success(o.responseText);
break;
case 'XML':
success(o.responseXML);
break;
default:
success(JSON.parse(o.responseText));
}
}else{
error();
}
complete();
clearTimeout(t);
t = null;
o = null;
}
}

o.open(type, url, async);
type === 'POST' && o.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
o.send(type === 'GET' ? null : formatDatas(data));

t = setTimeout(function(){
o.abort();
clearTimeout(t);
t = null;
o = null;
throw new Error('本次请求已超时,API地址:' + url);
}, timeout);
}

function formatData(obj){
var str = '';
for(var key in obj){
str += key + '=' + obj[key] + '&';
}
return str.replace(/&$/, '');
}

function randomNum(){
var num = '';
for(var i = 0; i < 20; i++){
num += Math.floor(Math.random() * 10);
}
return num;
}

return {
ajax: function(opt){
_doAjax(opt);
},

post: function(url, data, dataType, successCB, errorCB, completeCB){
_doAjax({
type: 'POST',
url: url,
data: data,
dataType: dataType,
success: csuccessCB,
error: errorCB,
complete: completeCB
});
},

get: function(url, dataType, successCB, errorCB, completeCB){
_doAjax({
type: 'GET',
url: url,
dataType: dataType,
success: csuccessCB,
error: errorCB,
complete: completeCB
})
}
}
})();
  • XMLHttpRequest标准又分为Level 1和Level 2
    • Level1
      • 无法发送跨域请求
      • 无法发送非纯文本内容
      • 无法获取传输进度
    • Level2
      • 可以发送跨域请求
      • 支持获取二进制数据(非纯文本数据)
      • 支持上传文件
      • formData对象
      • 可以获取传输进度
      • 可以设置超时时间
      • 但存在兼容性问题
        • IE8/9/Opara Mini不支持xhr对象
        • IE10/11不支持响应类型为JSON
        • 部分浏览器不支持超时设置
        • 部分浏览器不持支blob(文件对象的二进制数据)
  • xhr.status/xhr.statusText:服务器回应的HTTP状态码/服务器发送的状态提示
    • 200,OK,访问正常
    • 301,Moved Permanently,永久移动
    • 302,Move temporarily,暂时移动
    • 304,Not Modified,未修改
    • 307,Temporary Redirect,暂时重定向
    • 401,Unauthorized,未授权
    • 403,Forbidden,禁止访问
    • 404,Not Found,未发现指定网址
    • 500,Internal Server Error,服务器发生错误
  • xhr.onloadstart:绑定HTTP请求发出的监听函数
  • xhr.onerror:绑定请求失败的监听函数(修改封装的AJAX)
  • xhr.onload:绑定请求成功完成的监听函数
  • xhr.onabort:绑定请求中止(调用了abort()方法)的监听函数
  • xhr.onloadend:绑定请求完成(不管成功与失败)的监听函数

防抖:n秒内触发一个事件,以最后一次触发为准

节流:n秒内只触发一次事件