第 40 题(如何实现一个 ajax())

主要使用以下文件
config.js:ajax 请求配置核心文件
loading.js:element-ui 请求加载动画
index.js:二次封装 config.js 请求并导出该方法,配置请求拦截器、响应拦截器
index.vue:调用 ajax 的示例页面
注意:推荐在 api 目录统一管理所有接口,如果遇到报错请调整正确引用路径
config.js

import loading from './loading.js'; // 加载动画类const animation = false; // 接口加载动画 const intTimer = 10; // 接口请求超时时间(秒)class Config { constructor(data) { this.method = data.method; this.url = data.url; this.param = data.param || {}; this.header = data.header || {}; this.interceptors = data.interceptors; this.response = data.response; return this.filter(); }// 创建XHR对象 createXHR() { if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari return new XMLHttpRequest(); } else { // code for IE6, IE5 return new ActiveXObject('Microsoft.XMLHTTP'); } }// HTTP请求 xhrRequest(header, method, url, param, async, interceptors, response) { return new Promise(resolve => { var xhr = this.createXHR(); if (animation == true) { loading.requestStart(); // 执行动画 }// 请求拦截 if (interceptors({ header, method, url: this.url, param: this.param, async })) { xhr.open(method, url, async); xhr.timeout = 1000 * intTimer; //设置xhr请求的超时时间 Object.keys(header).map(key => { xhr.setRequestHeader(key, header[key]); }); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; application/json; charset=utf-8'); xhr.send(param); xhr.onreadystatechange = () => { if (xhr.readyState == 4 && xhr.status == 200) { loading.requestEnd(); // 结束动画 try { let data = https://www.it610.com/article/JSON.parse(xhr.responseText); resolve(response(data, { header, method, url: this.url, param: this.param, async })); } catch (error) { console.log('接口返回没有任何信息!'); resolve(false); } } else { return 'request is unsucessful ' + xhr.status; } }; } else { console.error('request interceptor', '请求未发出, 请求拦截器已生效!'); }// 请求超时方法 xhr.ontimeout = function(e) { console.log('接口请求超时!'); loading.requestEnd(); // 结束动画 }; // 请求错误方法 xhr.onerror = function(e) { console.log('接口请求失败'); loading.requestEnd(); // 结束动画 }; }); }// 参数转换 convParams(param) { let mark = '?'; let hasMark = this.url.indexOf(mark) > 0; // 是否包含特殊字符 if (hasMark) { mark = '&'; }let newParams = ''; let i = 0; for (let key in param) { if (i > 0) { newParams += `&${key}=${param[key]}`; } else { newParams += `${mark}${key}=${param[key]}`; } i++; } return newParams; }// 数据GET、POST请求处理 filter() { let obj = { header: this.header, method: this.method, url: this.url, param: {}, async: true, interceptors: this.interceptors, response: this.response }; // 接口名称拼接位置:(1、url) (2、param)let newParams = this.convParams(this.param); if (this.method == 'GET') { obj.url += newParams; } else { newParams = newParams.replace('?', ''); obj.param = newParams; }return this.xhrRequest(obj.header, obj.method, obj.url, obj.param, obj.async, obj.interceptors, obj.response); } }export default Config;

【第 40 题(如何实现一个 ajax())】loading.js
import { Loading } from 'element-ui'; class animation { constructor() { this.needLoadingRequestCount = 0; this.loading }/** * 动画开始 */ requestStart() { if (this.needLoadingRequestCount === 0) { this.loading = Loading.service({ lock: true, text: 'loading...', background: 'rgba(0, 0, 0, 0.7)' }); } this.needLoadingRequestCount++; }/** * 动画结束 */ requestEnd() { if (this.needLoadingRequestCount <= 0) return; this.needLoadingRequestCount--; if (this.needLoadingRequestCount === 0) { this.loading.close(); } } }export default new animation()

index.js
import Config from './config.js'; /** * 接口请求方法 * @func request * @param {Object} method 请求方式: 仅支持GET、POST * @param {String} url 请求地址 * @param {Object} param 请求参数 */ let request = option => { // 配置默认请求参数return new Config({ header: { Authorization: 'APPCODE edc39cc1dc5f4c139498322115b99e51' }, method: option.method, url: option.url, param: option.param, interceptors: interceptors, response: response }); }; /** * 请求拦截器 * @func interceptors */ let interceptors = config => { return true; }; /** * 响应拦截器 * @func response */ let response = (data, config) => { let res; // 处理返回格式 if (data.res) { res = data.res; } else if (data.data) { res = data.data; } else { res = data; } return res; }; export default request;

index.vue

文章的内容/灵感都从下方内容中借鉴
  • 【持续维护/更新 500+前端面试题/笔记】https://github.com/noxussj/In...
  • 【大数据可视化图表插件】https://www.npmjs.com/package...
  • 【利用 THREE.JS 实现 3D 城市建模(珠海市)】https://3d.noxussj.top/

    推荐阅读