使用 Promise 封装 XMLHttpRequest 以及 fetch 实现 AJAX
远古时代的前端程序猿都是使用JQ的ajax来请求服务器的:
$.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
console.log( msg );
}
});
JQ 的 AJAX 底层是使用了 XMLHttpRequest 对象,对比现代浏览器所支持的 Fetch API,很多人都觉得 XHR 对象真是太麻烦了,但实际上我使用 fetch 的时候发现 fetch 并不是那么简单好用,相反反而觉得 XHR 对象竟然还好用一些,因为 fetch 有很多缺点(比如不支持监听进度…)
封装 AJAX
拿 XHR 和 fetch 分别封装一个 AJAX,用法如下:
export default {
//GET请求
get(url, data = null) {
// return this.ajax('GET', url, null);
return this.fetch('GET', url, data);
},
//POST请求
post(url, data = null) {
// return this.ajax('POST', url, data);
return this.fetch('POST', url, data);
},
//PUT请求
put(url, data = null) {
// return this.ajax('PUT', url, data);
return this.fetch('PUT', url, data);
},
//Delete请求
del(url, data = null) {
// return this.ajax('DELETE', url, data);
return this.fetch('DELETE', url, data);
},
ajax(method, url, data) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest, params = [];
xhr.responseType = 'json';// 指定返回类型
xhr.onload = () => {
switch (xhr.status) {
case 200: resolve(xhr.response);break;
case 204: resolve();break;
case 401:// 401登录失败处理
//do something
reject();
break;
default: reject({status: xhr.status, res: xhr.response});
}
};
if (data) {// 将参数编码成表单的键值对形式
for (let k in data) params.push(`${encodeURIComponent(k)}=${encodeURIComponent(data[k])}`);
data = params.join('&');
}
xhr.open(method, url, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded;charset=utf-8');// 设置content-type
xhr.withCredentials = true;// 支持跨域发送cookies
xhr.send(data);
});
},
fetch(method, url, data) {
let params = [], init = {
method,
mode: 'cors',
headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'},
credentials: 'include',// 支持跨域发送cookies
};
if (data) {// 将参数编码成表单的键值对形式
for (let k in data) params.push(`${encodeURIComponent(k)}=${encodeURIComponent(data[k])}`);
if (method === 'GET') {
url += '?' + params.join('&');
} else {
init.body = params.join('&');
}
}
return fetch(url, init).then(e => {
switch (e.status) {
case 200: return e.json();
case 204: break;
case 401:// 401登录失败统一处理
//do something
return Promise.reject();
case 403: return e.json().then(e => Promise.reject(e));// 服务端主动抛出错误
default: return Promise.reject({status_code: 500, message: '服务器繁忙, 请稍后再试'});
}
})
}
}
Vue 项目中使用:
// main.js引入
import Api from './api'
Vue.prototype.api = Api;
// Promise
this.get('https://baidu.com/api/').then(e => console.log(e));
// Async/Await
let res = await this.get('https://baidu.com/api/');
console.log(res);
发布评论
还没有评论,快来抢沙发吧!