结合class和模块化
“ajax封装”目录
ajax.js (Ajax类)
// 工具函数
import { serialize, addURLData, serializeJSON } from './utils.js';
// 默认参数
import DEFAULTS from '.defaults.js'
class Ajax{
constructor(url, options){
// options分用户参数、默认参数
this.url = url;
this.options = Object.assign({}, DEFAULTS, options);
// 初始化
this.init();
}
// 初始化
init() {
const xhr = new XMLHttpRequest();
this.xhr = xhr;
// 绑定响应事件处理程序
this.bindEvents();
this.xhr.open(this.options.method, this.url+this.addParam(), true); // true表示异步
// 设置 responseType
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.ok()) {
success(xhr.response, xhr);
} else {
httpCodeError(xhr.status, xhr);
}
},
false
);
// error
// 当请求遇到错误时,将触发 error 事件
xhr.addEventListener(
'error',
() => {
error(xhr);
},
false
);
// abort
xhr.addEventListener(
'abort',
() => {
abort(xhr);
},
false
);
// timeout
xhr.addEventListener(
'timeout',
() => {
timeout(xhr);
},
false
);
}
// 检测响应的 HTTP 状态码是否正常
ok() {
const xhr = this.xhr;
return (xhr.status >= 200 && xhr.status < 300) || xhr.status === 304;
}
// 在地址上添加数据
addParam() {
const { params } = this.options;
if (!params) return '';
// 有时候url上面已经带参数,即?words=js;有时候不带参数,要先加?
return addURLData(this.url, serialize(params));
}
// 设置 responseType
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;
if (!this.isSendData()) {
return xhr.send(null);
}
let resultData = null;
const { data } = this.options;
// 发送 FormData 格式的数据
if (this.isFormData()) {
resultData = data;
} else if (this.isFormURLEncodedData()) {
// 发送 application/x-www-form-urlencoded 格式的数据
this.setContentType(CONTENT_TYPE_FORM_URLENCODED);
resultData = serialize(data);
} else if (this.isJSONData()) {
// 发送 application/json 格式的数据
this.setContentType(CONTENT_TYPE_JSON);
resultData = serializeJSON(data);
} else {
// 发送其他格式的数据
this.setContentType();
resultData = data;
}
xhr.send(resultData);
}
// 是否需要使用 send 发送数据
isSendData() {
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;
}
// 是否发送 application/x-www-form-urlencoded 格式的数据
isFormURLEncodedData() {
return this.options.contentType
.toLowerCase()
.includes(CONTENT_TYPE_FORM_URLENCODED);
}
// 是否发送 application/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);
}
// 获取 XHR 对象
getXHR() {
return this.xhr;
}
}
export default Ajax;
default.js (存放默认参数 )
// 默认参数
const DEFAULTS = {
method: 'GET',
// 请求头携带的数据
params: null,
//params: {
// username: 'jinhuai',
// age: '22'
//}
// username=jinhuai&age=22
// 请求体携带的数据
data: null,
//data: {
// username: 'jinhuai',
// age: '22'
//}
// data: FormData数据
contentType: 'application/x-www-form-urlencoded',
responseType:'', //默认文本
timeoutTime: 0, // 默认没有超时时间
withCredentials: false,
// 方法
success(){},
httpCodeError(){},
error(){},
abort(){},
timeout(){}
};
export default DEFAULTS;
utils.js (工具函数)
const serialize = param => {
const results =
for(const [key, value] of Object.entries(param)){
results.push(`${encodeURLComponent(key)}=${encodeURLComponent(value)}`);
}
// ['username=jinhuai', 'age=22'];
return results.join('&');
}
// 数据序列化成 JSON 格式的字符串
const serializeJSON = param => {
return JSON.stringify(param);
};
// 给 URL 添加参数
// www.imooc.com?words=js&
const addURLData = (url, data) => {
if (!data) return '';
const mark = url.includes('?') ? '&' : '?';
return `${mark}${data}`;
};
export { serialize, addURLData, serializeJSON };
constants.js
// 常量
export const HTTP_GET = 'GET';
export const CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded';
export const CONTENT_TYPE_JSON = 'application/json';
index.js
import Ajax from './ajax.js';
const ajax = (url, options) => {
return new Ajax(url, options).getXHR();
};
const get = (url, options) => {
return ajax(url, { ...options, method: 'GET' });
};
const getJSON = (url, options) => {
return ajax(url, { ...options, method: 'GET', responseType: 'json' });
};
const post = (url, options) => {
return ajax(url, { ...options, method: 'POST' });
};
export { ajax, get, getJSON, post };
导入
<script type="module">
import { ajax, get, getJSON, post } from './ajax/index.js';
const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const url = 'https://www.iimooc.com/api/http/search/suggest?words=js';
// const url = './414.html';
const xhr = ajax(url, {
method: 'GET',
params: { username: 'alex' },
data: {
age: 18
},
responseType: 'json',
// timeoutTime: 10,
success(response) {
console.log(response);
},
httpCodeError(err) {
console.log('http code error', err);
},
error(xhr) {
console.log('error', xhr);
},
abort(xhr) {
console.log('abort', xhr);
},
timeout(xhr) {
console.log('timeout', xhr);
}
});
xhr.abort();
</script>