第 40 题:如何实现一个 ajax?

  • A+
所属分类:Web前端
摘要

主要使用以下文件config.js:ajax 请求配置核心文件loading.js:element-ui 请求加载动画

主要使用以下文件

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 = 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; 

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

<script> import request from './index.js';  export default {     mounted() {         new request({             method: 'GET', // 请求方式: GET、POST             url: 'http://10.10.10.10/xxx/xxx', // 请求地址             param: {} // 请求参数         }).then(res => {             console.log('res', res);         });     } }; </script> 

文章的内容/灵感都从下方内容中借鉴