XMLHttpRequest—必知必会
前言
- 做web开发,我们都知道浏览器通过
XMLHttpRequest
对象进行http通信 - 在实际开发中我们使用的是各种框架封装了的
XMLHttpRequest
对象,对具体实现往往一知半解.所以为了换框架好上手,请求有异常好调试,有必要深入学习一下XMLHttpRequest
- 本文从基础
XMLHttpRequest
开始,一步步把它封装为更实用的框架级别
实例
- 一个最简单的http请求
let xhr = new XMLHttpRequest();
xhr.open('GET', '/url', true);
xhr.send();
- 一个稍微完整的http请求
let xhr = new XMLHttpRequest();
// 请求成功回调函数
xhr.onload = e => {
console.log('request success');
};
// 请求结束
xhr.onloadend = e => {
console.log('request loadend');
};
// 请求出错
xhr.onerror = e => {
console.log('request error');
};
// 请求超时
xhr.ontimeout = e => {
console.log('request timeout');
};
// 请求回调函数.XMLHttpRequest标准又分为Level 1和Level 2,这是Level 1和的回调处理方式
// xhr.onreadystatechange = () => {
// if (xhr.readyState !== 4) {
// return;
// }
// const status = xhr.status;
// if ((status >= 200 && status < 300) || status === 304) {
// console.log('request success');
// } else {
// console.log('request error');
// }
// };
xhr.timeout = 0; // 设置超时时间,0表示永不超时
// 初始化请求
xhr.open('GET/POST/DELETE/...', '/url', true || false);
// 设置期望的返回数据类型 'json' 'text' 'document' ...
xhr.responseType = '';
// 设置请求头
xhr.setRequestHeader('', '');
// 发送请求
xhr.send(null || new FormData || 'a=1&b=2' || 'json字符串');
- 很多东西一看就懂,但当真正去用的时候就会发现很多问题
- 为了深入学习,本着使XMLHttpRequest更易用的原则,模仿jQuery ajax封装
XMLHttpRequest
封装XMLHttpRequest
const http = {
/**
* js封装ajax请求
* >>使用new XMLHttpRequest 创建请求对象,所以不考虑低端IE浏览器(IE6及以下不支持XMLHttpRequest)
* >>使用es6语法,如果需要在正式环境使用,则可以用babel转换为es5语法 https://babeljs.cn/docs/setup/#installation
* @param settings 请求参数模仿jQuery ajax
* 调用该方法,data参数需要和请求头Content-Type对应
* Content-Type data 描述
* application/x-www-form-urlencoded 'name=哈哈&age=12'或{name:'哈哈',age:12} 查询字符串,用&分割
* application/json name=哈哈&age=12' json字符串
* multipart/form-data new FormData() FormData对象,当为FormData类型,不要手动设置Content-Type
* 注意:请求参数如果包含日期类型.是否能请求成功需要后台接口配合
*/
ajax: (settings = {}) => {
// 初始化请求参数
let _s = Object.assign({
url: '', // string
type: 'GET', // string 'GET' 'POST' 'DELETE'
dataType: 'json', // string 期望的返回数据类型:'json' 'text' 'document' ...
async: true, // boolean true:异步请求 false:同步请求 required
data: null, // any 请求参数,data需要和请求头Content-Type对应
headers: {}, // object 请求头
timeout: 1000, // string 超时时间:0表示不设置超时
beforeSend: (xhr) => {
},
success: (result, status, xhr) => {
},
error: (xhr, status, error) => {
},
complete: (xhr, status) => {
}
}, settings);
// 参数验证
if (!_s.url || !_s.type || !_s.dataType || _s.async === undefined) {
alert('参数有误');
return;
}
// 创建XMLHttpRequest请求对象
let xhr = new XMLHttpRequest();
// 请求开始回调函数
xhr.addEventListener('loadstart', e => {
_s.beforeSend(xhr);
});
// 请求成功回调函数
xhr.addEventListener('load', e => {
const status = xhr.status;
if ((status >= 200 && status < 300) || status === 304) {
let result;
if (xhr.responseType === 'text') {
result = xhr.responseText;
} else if (xhr.responseType === 'document') {
result = xhr.responseXML;
} else {
result = xhr.response;
}
// 注意:状态码200表示请求发送/接受成功,不表示业务处理成功
_s.success(result, status, xhr);
} else {
_s.error(xhr, status, e);
}
});
// 请求结束
xhr.addEventListener('loadend', e => {
_s.complete(xhr, xhr.status