1. 设置常量
可以根据需要设置一些常量
// 常量
export const HTTP_GET = 'GET';
export const CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded';
export const CONTENT_TYPE_JSON = 'application/json';
2. 封装工具类
主要用于数据的转换及URL处理
// 将数组序列化成URLEncoded格式的字符串
const serializeURLEncoded = param => {
const results = [];
for (const [key, value] of Object.entries(param)) {
results.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
}
return results.join('&');
};
// 将数组序列化成JSON格式的字符串
const serializeJSON = param => {
return JSON.stringify(param);
};
// 获取合法格式的参数字符串
const addURLData = (url, data) => {
if (!data) {
return '';
}
const mark = url.includes('?') ? '&' : '?';
return `${mark}${data}`;
};
export { serializeURLEncoded, serializeJSON, addURLData };
3. 设置默认参数
当用户未指定参数时,将使用默认参数
// 引入常量
import { HTTP_GET, CONTENT_TYPE_FORM_URLENCODED } from './constants.js';
// 设置默认参数
const DEFAULTS = {
// 请求方法
method: HTTP_GET,
// 请求头参数
params: null,
// 请求体参数
data: null,
// Content-Type类型
contentType: CONTENT_TYPE_FORM_URLENCODED,
// Response-Type类型
responseType: '',
// 超时时间
timeoutTime: 0,
// 是否携带Cookie
withCredentials: false,
// 成功时执行的方法
success() { },
// 状态码异常时执行的方法
httpCodeError() { },
// 失败时执行的方法
error() { },
// 终止时执行的方法
abort() { },
// 超时时执行的方法
timeout() { }
};
export default DEFAULTS;
4. 设计Ajax类
// 引入常量
import { HTTP_GET, CONTENT_TYPE_JSON, CONTENT_TYPE_FORM_URLENCODED } from './constants.js';
// 引入函数
import { serializeURLEncoded, serializeJSON, addURLData } from './utils.js';
// 引入默认参数
import DEFAULTS from './defaults.js';
// 定义Ajax类
class Ajax {
// 构造函数
constructor(url, options) {
this.url = url;
this.options = Object.assign({}, DEFAULTS, options);
this.init();
}
// 初始化的方法
init() {
// 初始化XMLHttpRequest
const xhr = new XMLHttpRequest();
this.xhr = xhr;
// 绑定事件
this.bindEvents();
// 配置请求
xhr.open(this.options.method, this.url + this.addParam(), true);
// 设置Response-Type
this.setResponseType();
// 设置跨域是否携带Cookie
this.setCookie();
// 设置超时
this.setTimeout();
// 发送请求
this.sendData();
}
// 绑定事件的方法
bindEvents() {
const xhr = this.xhr;
const { success, httpCodeError, error, abort, timeout } = this.options;
// load事件
xhr.addEventListener('load', () => {
if (this.isReady()) {
success(xhr.response, xhr);
} else {
error(xhr);
}
}, false);
// error事件
xhr.addEventListener('error', () => {
error(xhr);
}, false);
// abort事件
xhr.addEventListener('abort', () => {
abort(xhr);
}, false);
// timeout事件
xhr.addEventListener('timeout', () => {
timeout(xhr);
}, false)
}
// 判断请求是否得到正确的响应的方法
isReady() {
const xhr = this.xhr;
return (xhr.status >= 200 && xhr.status < 300) || xhr.status === 304;
}
// 在URL上增加参数的方法
addParam() {
const { params } = this.options;
if (!params) {
return '';
}
return addURLData(this.url, serializeURLEncoded(params));
}
// 设置Response-Type的方法
setResponseType() {
this.xhr.responseType = this.options.responseType;
}
// 设置跨域是否携带Cookie的方法
setCookie() {
if (this.options.withCredentials) {
this.xhr.withCredentials = true;
}
}
// 设置超时时长的方法
setTimeout() {
const { timeoutTime } = this.options;
if (timeoutTime > 0) {
this.xhr.timeout = timeoutTime;
}
}
// 发送请求的方法
sendData() {
const xhr = this.xhr;
// 若无需传输数据,则直接send
if (!this.isHasData()) {
return xhr.send(null);
}
let resultData = null;
const { data } = this.options;
// 按数据类型进行整理
if (this.isFormData()) {
resultData = data;
} else if (this.isURLEncodedData()) {
this.setContentType(CONTENT_TYPE_FORM_URLEncoded);
resultData = serializeURLEncoded(data);
} else if (this.isJSONData()) {
this.setContentType(CONTENT_TYPE_JSON);
resultData = serializeJSON(data);
} else {
this.setContentType();
resultData = data;
}
xhr.send(resultData);
}
// 判断是否需要传输数据的方法
isHasData() {
const { data, method } = this.options;
if (!data) {
return false;
}
if (method.toLowerCase() === HTTP_GET.toLowerCase()) {
return false;
}
return true;
}
// 判断数据类型是否为FormData的方法
isFormData() {
return this.options.data instanceof FormData;
}
// 判断数据类型是否为URLEncoded的方法
isURLEncodedData() {
return this.options.contentType.toLowerCase().includes(CONTENT_TYPE_FORM_URLENCODED);
}
// 判断数据类型是否为JSON的方法
isJSONData() {
return this.options.contentType.toLowerCase().includes(CONTENT_TYPE_JSON);
}
// 设置Content-Type的方法
setContentType(contentType = this.options.contentType) {
if (!contentType) {
return;
}
this.xhr.setRequestHeader('Content-Type', contentType);
}
// 获取XMLHttpRequest对象
getXMLHttpRequest() {
return this.xhr;
}
}
export default Ajax;