XMLHttpRequest版本
- level 1
- 传输纯文本数据
- 无法跨域
- level 2
- 支持超时时间
- 支持跨域(需要后端配合设置access-control-allow-origin)
- 支持二进制数据(文件、formdata对象),可获取进度
响应状态
- 200 成功
- 301 永久性移动,浏览器输入了一个网址后,会自动跳转到另一个网址。
- 302 暂时性移动,浏览器输入一个网址A后,自动跳转到另一个网址B。搜索引擎可能会记录网址A,打开网站后依旧为A。具体参见
- 304 未修改,使用本地缓存文件。如果etag和modified-since时间相同,则使用本地缓存文件。
- 307 暂时重定向。参见
- 400 语法错误,被禁止访问,url拼写错误。
- 401 未授权。表示缺少认证信息,认证信息可能是账号密码或指定的终端。
- 403 请求被拒绝。由于服务器目录禁止被操作而返回的错误。
- 404 找不到访问的资源。
- 500 服务器端程序发生错误。
- 503 服务器超负荷运行返回的错误,稍后访问可能会成功。
设置超时
- timeout 为超时时间,超过后则自动断开连接,但兼容性不是很好。
xhr.timeout = 100;
生命周期
-
onloadstart >> readyState === 4 >> onload || onerror || onabort >> onloadend
封装ajax完整版
var $ = function (w) {
function formatData (data) {
if(!data) return null;
var str = '',
toStr = Object.prototype.toString;
for( var key in data ) {
if ( toStr.call(data[key]) === '[object Object]'
|| toStr.call(data[key]) === '[object Array]' ) {
// 待实现
}
str += key + '=' + data[key] + '&';
}
str = str.replace(/&$/, '');
return str;
}
function _doAjax(opt) {
var xhr = null;
if (w.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
opt = opt || {};
if (!opt.url) throw new Error("url为必填项");
let url = opt.url,
type = (opt.type || 'GET').toUpperCase(),
data = opt.data || null,
contentType = opt.contentType || 'application/x-www-form-urlencoded', // 只有post请求时,需要设置请求的数据类型
dataType = (opt.dataType || 'json').toLowerCase(), // 服务器返回的数据类型
async = (opt.async + '') === 'false' ? false : true,
timeout = opt.timeout || 30000, // 如果设置0,默认为30秒 todo:封装其他类型 回调等
success = opt.success || function () {},
error = opt.error || function () {},
complete = opt.complete || function () {},
tId = null;
xhr.onreadystatechange = function () { // 此函数必须在send方法执行前进行定义,否则无法实现同步
if (xhr.readyState === 4) {
if (xhr.status === 304 || (xhr.status >= 200 && xhr.status < 300)) {
switch (dataType) {
case 'json':
success(JSON.parse(xhr.responseText));
break;
case 'text':
success(xhr.responseText);
break;
case 'xml':
case 'html':
success(xhr.responseXml);
break;
default :
success(xhr.responseText);
}
} else {
error(xhr.statusText);
}
clearTimeout(tId);
tId = null;
xhr = null;
complete("The request of " + url + " has completed");
}
}
tId = setTimeout(function () {
clearTimeout(tId);
xhr.abort(); // 终止已发出的请求
tId = null;
xhr = null;
throw new Error('The request has time out');
}, timeout);
xhr.open(type, url, async);
if (type === 'POST') xhr.setRequestHeader('Content-Type', contentType);
// xhr.setResponseType = dataType; // TOOD: 待优化,将xml html转为document 设置blob、arrayBuffer、ms-stream、"" 类型
xhr.send(formatData(data)); // 如果是同步,send方法会等待readyState为4的时候才会继续执行后面的代码
}
return {
ajax: function (options) {
_doAjax(options);
},
post: function (url, data, cb) {
this.ajax({
url: url,
type: 'post',
data: data,
success: cb,
});
},
get: function (url, cb) {
this.ajax({
url: url,
success: cb,
});
}
};
}(window);






网友评论