放下Axios,手写纯原生Ajax通信接口

3,074 阅读4分钟

前言

axios作为vue框架中最常用的ajax工具包之一,可以与后台API接口进行通信,传送或接收数据,在前后端分离开发中,发挥了通信桥梁的重要作用。

虽然像axios这样的第三方工具包很好用,但是这类工具包并不能很好地帮助前段开发人员,尤其是新人理解JavaScript原生的ajax通信机制。

因此,本文将通过JS原生的ajax通信实例,为读者详细介绍原生ajax通信机制和使用方法。

关于Ajax

1999年,微软公司发布 IE 浏览器5.0版,第一次引入新功能:允许 JavaScript 脚本向服务器发起 HTTP 请求。这个功能当时并没有引起注意,直到2004年 Gmail 发布和2005年 Google Map 发布,才引起广泛重视。2005年2月,AJAX 这个词第一次正式提出,它是 Asynchronous JavaScript and XML 的缩写,指的是通过 JavaScript 的异步通信,从服务器获取 XML 文档从中提取数据,再更新当前网页的对应部分,而不用刷新整个网页。后来,AJAX 这个词就成为 JavaScript 脚本发起 HTTP 通信的代名词,也就是说,只要用脚本发起通信,就可以叫做 AJAX 通信。W3C 也在2006年发布了它的国际标准。

具体来说,Ajax 包括以下几个步骤。

  1. 创建 XMLHttpRequest
  2. 实例发出 HTTP
  3. 请求接收服务器传回的数据
  4. 更新网页数据

简单来说,Ajax 通过原生的XMLHttpRequest对象发出 HTTP 请求,得到服务器返回的数据后,再进行处理。

创建Ajax通信接口

在这里插入图片描述
如图所示,本文将采用封装输出Axios通信接口的方式,封装原生的Ajax通信接口,方便读者对两者的实际应用进行对比。

1. 生成通信接口

首先,我们需要封装一个类似Axios的通信接口,该接口将XMLHttpRequest对象封装在promise对象中。

具体代码如下:

const ajax = function({
    // 定义接口参数
    method = 'GET', // 请求方式:get, post, put, delete 
    url = '', // 请求连接
    data = null, // post data
    params = null, // get params
    baseURL = '', // domain URL
    withCredentials = false // api验证请求
} = {}) {
    const promise = new Promise(function(resolve, reject) {
        // api url
        let apiUrl = baseURL + url;
        // create get params
        if (params) {
            let urlParams = [];
            for (let key in params) {
                urlParams.push(`${key}=${params[key]}`)
            }
            apiUrl += `?${urlParams.join('&&')}`;
        }
        // access
        const accessHandler = function() {
            // readState === 4, 表示api接口请求完成
            if (this.readyState !== 4) {
                return;
            }
            // 根据status状态码进行相关操作
            if (this.status === 200) {
                resolve(JSON.parse(this.response));
            } else {
                reject(new Error(this.statusText));
            }
        };
        // error
        const errorHandler = function() {
            console.error(this.statusText);
        };
        // timeout
        const timeoutHandler = function() {
            console.error(`The request for ${apiUrl} timed out.`);
        };
        // client
        const client = new XMLHttpRequest(); // 生成XMLHttpRequest实例对象
        client.open(method, apiUrl, true); // 配置client参数
        // status
        client.onreadystatechange = accessHandler; // 请求成功
        client.ontimeout = timeoutHandler; // 请求超时 
        client.onerror = errorHandler; // 请求错误
        // config
        client.responseType = "json"; // 返回值:json
        client.timeout = 10 * 1000; // 超时时间:10s
        client.withCredentials = withCredentials; // 设置验证
        client.setRequestHeader("Accept", "application/json"); // 设置请求头
        // send
        client.send(data); // 发生请求

    });

    return promise; // 输出promise对象
};

export { ajax }

2. 封装通信接口

将原生Ajax接口其进行封装,方便在vue项目中使用。

具体代码如下:

// 配置API接口地址
const root = ''

// 引入原生Ajax
import { ajax } from './ajax'

// 自定义判断元素类型JS
function toType(obj) {
    return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

// 参数过滤函数
function filterNull(params) {
    for (let key in params) {
        if (params[key] === null) {
            delete params[key]
        }
        if (toType(params[key]) === 'string') {
            params[key] = params[key].trim()
        } else if (toType(params[key]) === 'object') {
            params[key] = filterNull(params[key])
        } else if (toType(params[key]) === 'array') {
            params[key] = filterNull(params[key])
        }
    }
    return params
}

// 封装Ajax接口

function apiAjax(method, url, params, success, failure) {
    if (params) {
        params = filterNull(params)
    }
    ajax({
            method: method,
            url: url,
            data: method === 'POST' || method === 'PUT' ? params : null,
            params: method === 'GET' || method === 'DELETE' ? params : null,
            baseURL: root,
            withCredentials: false
        })
        .then(function(res) {
            if (success) {
                success(res)
            }
        })
        .catch(function(err) {
            if (failure) {
                failure(err)
            } else {
                throw err;
            }
        })
}

// 返回在vue模板中的调用接口
export default {
    get: function(url, params, success, failure) {
        return apiAjax('GET', url, params, success, failure)
    },
    post: function(url, params, success, failure) {
        return apiAjax('POST', url, params, success, failure)
    },
    put: function(url, params, success, failure) {
        return apiAjax('PUT', url, params, success, failure)
    },
    delete: function(url, params, success, failure) {
        return apiAjax('DELETE', url, params, success, failure)
    }
}

调用Ajax通信接口

完成Ajax接口封装后,在main.js文件中直接引入。

import ajaxApi from './api/ajaxApi'

Vue.prototype.$ajaxApi = ajaxApi

最后,在vue页面进行使用。

  created() {
    this.getDataFromApi();
  },
  data() {
    return {
      tableData: []
    };
  },
  methods: {
    getDataFromApi() {
      this.$ajaxApi.get(
        "/data/tableData", // mock 数据接口
        null,
        Response => {
          this.tableData = Response;
          console.log(Response);
        },
        Error => {
          throw Error;
        }
      );
    }
  }

具体效果如下图。

在这里插入图片描述
在这里插入图片描述

总结

相信通过本文,你对原生ajax通信已经有了一定的了解。需要提醒的是,本文实例是本人根据mock数据接口编写的,因此,在通用性上面,可能有所不足。如果你想直接使用本文实例,可能需要根据你实际调用的接口进行调整。

当然,你也可以直接访问本人的github项目,项目地址:github.com/jiangjiahen…

最后,祝工作顺利,生活愉快。

在这里插入图片描述