使用Promise封装XMLHttpRequest以及fetch实现AJAX

10831543506011.gif

远古时代的前端程序猿都是使用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有很多缺点(比如不支持监听进度…)

拿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 await let res = this.get('https://baidu.com/api/'); console.log(res);

发布评论
还没有评论,快来抢沙发吧!