JavaScript封装axios的实现详解

目录
  • 摘要
  • 1.post方法
  • 2.create方法
  • 3.拦截器
  • 4.代码

摘要

在vue中,我们调用接口使用的都是axios,使用之前我们也会进行一定的封装,然后再进行使用。

在这里,我们主要说一下axios的实现原理,以及如何使用原生的js来自己封装出一个axios。

这里实现出几个主要的方法,包括post请求方法,create配置方法,以及拦截器的方法。

1.post方法

在我们写方法之前,肯定是要先自己写一个类出来,里面的内容先不用写。

然后再在类的下面写出post的方法:

function iaxios () {
}
iaxios.prototype.post = function (url, data){
}

OK,现在我们来实现这个方法。

如果我们想用原生的js来实现post请求,我们应该这样做:

    var xhr = new XMLHttpRequest();
    xhr.open('post', url, true);
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4) {
        if ((xhr.status == 200 || xhr.status == 304)) {
          resolve(xhr.responseText)
        } else {
          reject(xhr.responseText)
        }
      }
    };
    xhr.send(data)

但是我们直接把这段代码放进去的话,会有一点问题:

1.官方的axios返回的是一个promise对象

2.官方的axios.post方法传的data参数是一个对象,原生的是一个字符串

所以为了解决第一个问题,我们可以在方法内返回一个promise对象,而第二个问题可以使用JSON.stringfy()这个方法解决。

iaxios.prototype.post = function (url, data) {
  //返回promise对象
  return new Promise((resolve, reject) => {
    var xhr = new XMLHttpRequest();
    xhr.open('post', url, true);
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4) {
        if ((xhr.status == 200 || xhr.status == 304)) {
          resolve(xhr.responseText)
        } else {
          reject(xhr.responseText)
        }
      }
    };
    xhr.send(JSON.stringify(data))
  })
}

这样我们就实现了post的这个方法了。

而对get方法这里就不再写一遍了(写的时候主要注意参数的问题就可以了)。

2.create方法

首先我们知道,axios的create方法主要是对请求头等参数的配置,而这个方法同样也会返回一个axios的实例,这个实例可以继续使用post等方法。

所以我们首先想到的是,这个方法应该返回一个实例对象,而这个实例对象下的属性会根据传进来的对象设置。

这里面我只列举两个属性:

iaxios.prototype.create = function (obj) {
  var emaxios = new iaxios()
  emaxios.headers = obj.headers;
  emaxios.baseUrl = obj.baseUrl;
  return emaxios;
}

但是我们调用完这个create方法后,我们已经有了一些配置,如果再调用post等方法,我们应该是携带着这些参数去调用psot方法,所以在post方法内我们也要修改一下。

我们首先写一个配置请求头的方法:

function setHeader (xhr, headers) {
  for (var i in headers) {
    xhr.setRequestHeader(i, headers[i]);
  }
}

然后在post方法内,在ajax请求发送之前调用这个方法就可以了:

    setHeader(xhr, this.headers);

3.拦截器

在axios中,拦截器分两种,分别是请求拦截和响应拦截。

二者的作用也是相差不多的,一个是希望在请求之前做什么,一个是希望在请求之后做什么。

我们先来写一下请求拦截(这里面不考虑use):

我们先想一下,interceptors一定是一个对象,并且下面有两个属性,分别是request和response。

那么我们就在类里面写一下:

function iaxios () {
  this.interceptors = {
    request (cb) {
    },
    response (aa) {
    },
  }
}

如果我们想在外边调用这个方法,会将一个回调函数传进来,

所以在我们这里我们需要把这个回调函数保存下来(考虑到有多个拦截器,所以我们采用数组保存)。

同时我们也要写一个data用于存放请求时的数据(因为在请求拦截器的回调函数中,有一个config参数,它包含着请求的数据)

function iaxios () {
  //保存拦截器中的回调函数
  this.saveRequest = []
  this.saveResponse = []
  //保存请求的数据
  this.data = {};
  let _this = this;
  this.interceptors = {
    request (cb) {
      _this.saveRequest.push(cb)
    },
    response (aa) {
      _this.saveResponse.push(aa)
    },
  }
}

现在拦截器的方法已经写好了,我们应该在什么时候调用呢?

请求拦截一定是在请求发送之前进行调用,我们拿post来举例子:

iaxios.prototype.post = function (url, data) {
  this.data = data;
  let _this = this;
  // this.saveRequest && this.saveRequest(this)
  //请求之前调用请求拦截的回调函数
  if (this.saveRequest) {
    this.saveRequest.forEach(fn => {
      fn(this)
    })
  }

我们只需要在请求之前,把想要传递的数据copy下来(用于当作参数)。

然后循环调用我们保存下来的方法(其实就是调用的时候传递回调函数)

这样就能实现请求拦截了。

那么响应拦截一定是在返回响应数据之前调用了:

        if ((xhr.status == 200 || xhr.status == 304)) {
          //用来保存返回的数据
          let newRespose = new Object;
          newRespose.data = JSON.parse(xhr.responseText);
          //在返回数据之前调用相应拦截器的回调函数
          if (_this.saveResponse) {
            _this.saveResponse.forEach(fn => {
              fn(newRespose)
            })
          }
          resolve(newRespose.data)

这里面我们创建的newRespose也是为了当作参数传递到响应拦截的方法里面。

这样的话响应拦截器的实现也完成了。

4.代码

最后再把整体的代码复制一份:

// const { resolve, reject } = require("core-js/fn/promise")
function iaxios () {
  //保存拦截器中的回调函数
  this.saveRequest = []
  this.saveResponse = []
  //保存请求的数据
  this.data = {};
  let _this = this;
  this.interceptors = {
    request (cb) {
      _this.saveRequest.push(cb)
    },
    response (aa) {
      _this.saveResponse.push(aa)
    },
  }
}
iaxios.prototype.post = function (url, data) {
  this.data = data;
  let _this = this;
  // this.saveRequest && this.saveRequest(this)
  //请求之前调用请求拦截的回调函数
  if (this.saveRequest) {
    this.saveRequest.forEach(fn => {
      fn(this)
    })
  }
  //返回promise对象
  return new Promise((resolve, reject) => {
    var xhr = new XMLHttpRequest();
    xhr.open('post', url, true);
    //设置请求头的配置
    setHeader(xhr, this.headers);
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4) {
        if ((xhr.status == 200 || xhr.status == 304)) {
          //用来保存返回的数据
          let newRespose = new Object;
          newRespose.data = JSON.parse(xhr.responseText);
          // _this.saveResponse && _this.saveResponse(newRespose)
          //在返回数据之前调用相应拦截器的回调函数
          if (_this.saveResponse) {
            _this.saveResponse.forEach(fn => {
              fn(newRespose)
            })
          }
          resolve(newRespose.data)
        } else {
          reject(xhr.responseText)
        }
      }
    };
    xhr.send(JSON.stringify(data))
  })
}
iaxios.prototype.get = function (url) {
  let _this = this;
  // this.saveRequest && this.saveRequest(this)
  //请求之前调用请求拦截的回调函数
  if (this.saveRequest) {
    this.saveRequest.forEach(fn => {
      fn(this)
    })
  }
  //返回promise对象
  return new Promise((resolve, reject) => {
    var xhr = new XMLHttpRequest();
    xhr.open('get', url, true);
    //设置请求头的配置
    setHeader(xhr, this.headers);
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4) {
        if ((xhr.status == 200 || xhr.status == 304)) {
          //用来保存返回的数据
          let newRespose = new Object;
          newRespose.data = JSON.parse(xhr.responseText);
          // _this.saveResponse && _this.saveResponse(newRespose)
          //在返回数据之前调用相应拦截器的回调函数
          if (_this.saveResponse) {
            _this.saveResponse.forEach(fn => {
              fn(newRespose)
            })
          }
          resolve(newRespose.data)
        } else {
          reject(xhr.responseText)
        }
      }
    };
    xhr.send()
  })
}
//返回一个新的实例并且复制obj的属性
iaxios.prototype.create = function (obj) {
  var emaxios = new iaxios()
  emaxios.headers = obj.headers;
  emaxios.baseUrl = obj.baseUrl;
  return emaxios;
}
//设置请求头的方法
function setHeader (xhr, headers) {
  for (var i in headers) {
    xhr.setRequestHeader(i, headers[i]);
  }
}
var taxios = new iaxios();
export {
  taxios
}

到此这篇关于JavaScript封装axios的实现详解的文章就介绍到这了,更多相关JS封装axios内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JS中封装axios来管控api的2种方式

    前言:我们在开发项目的时候,往往要处理大量的接口.并且在测试环境 开发环境 生产环境使用的接口baseurl都不一样 这时候如果在开发环境完成之后切换每一个接口的baseurl会变的非常的麻烦,(要去每一个发出请求的页面都要去修改地址) 所以为了更好的管控这些api,我们需要自己封装一个axios定义统一的接口baseurl 这样在环境的切换的时候更好的管控和修改.话不多说上代码!!! 自己创建一个api文件夹 即可 import axios from 'axios' 为了处理java字符串问题

  • JavaScript axios安装与封装案例详解

    1.下载axios插件 cnpm install axios -S 2.在main.js引入axios import axios from 'axios' Vue.prototype.$http = axios 3.创建axios实例 let service = axios.create({ baseURL: baseUrl, // url = base api url + request url withCredentials: true, // send cookies when cross

  • JavaScript封装axios的实现详解

    目录 摘要 1.post方法 2.create方法 3.拦截器 4.代码 摘要 在vue中,我们调用接口使用的都是axios,使用之前我们也会进行一定的封装,然后再进行使用. 在这里,我们主要说一下axios的实现原理,以及如何使用原生的js来自己封装出一个axios. 这里实现出几个主要的方法,包括post请求方法,create配置方法,以及拦截器的方法. 1.post方法 在我们写方法之前,肯定是要先自己写一个类出来,里面的内容先不用写. 然后再在类的下面写出post的方法: functio

  • Vue3中使用typescript封装axios的实例详解

    这个axios封装,因为是用在vue3的demo里面的,为了方便,在vue3的配置里面按需加载element-plus 封装axios http.ts import axios, { AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse } from 'axios' import { IResponseData } from '@/types' import { ElMessage, ElLoading, ILoadingInstance

  • 封装一下vue中的axios示例代码详解

    在vue项目中,和后台交互获取数据这块,我们通常使用的是axios库,它是基于promise的http库,可运行在浏览器端和node.js中.他有很多优秀的特性,例如拦截请求和响应.取消请求.转换json.客户端防御cSRF等.所以我们的尤大大也是果断放弃了对其官方库vue-resource的维护,直接推荐我们使用axios库.如果还对axios不了解的,可以移步axios文档. 安装 npm install axios; // 安装axios 好了,下面开始今天的正文. 此次封装用以解决: (

  • JavaScript 中断请求几种方案详解

    目录 1 Promise 中断调用链 中断Promise 包装abort方法--仿照Axios的CancelToken 2 RXJS的unsubscribe方法 3 Axios的CancelToken 1 Promise Promise有一个缺点是一旦创建无法取消,所以本质上Promise是无法被终止的. 但是我们可以通过中断调用链或中断Promise来模拟请求的中断. 中断调用链 中断调用链就是在某一个then/catch执行之后,后续的链式调用(包括then,catch,finally)不再

  • IOS 使用Block二次封装AFNetworking 3.0详解

    IOS 使用Block二次封装AFNetworking 3.0详解 现在我们网络请求大都用第三方工具-–AFNetworking: 其中,AFNetworking 3.0 是对 NSURLSession 进行的封装,简化了很多步骤,但是在现实开发中,我们可以将AFNetworking再次封装到一个类中,这样通过传去URL和Parameters 就可以进行网络请求. 具体实现步骤: 前期准备:导入AFNetworking第三方框架 1.新建一个工具类,继承自NSObject: 2.在.h 中宏定义

  • 玩转JavaScript OOP - 类的实现详解

    概述 当我们在谈论面向对象编程时,我们在谈论什么? 我们首先谈论的是一些概念:对象.类.封装.继承.多态. 对象和类是面向对象的基础,封装.继承和多态是面向对象编程的三大特性. JavaScript提供了对象却缺乏类,它不能像C#一样能显式地定义一个类. 但是JavaScript的函数功能非常灵活,其中之一就是构造函数,结合构造函数和原型对象可以实现"类". 对象和类的概念 对象 "对象"是面向对象编程中非常重要的一个概念,一个对象是一个"东西"

  • JavaScript显式数据类型转换详解

    基本概念 将值从一种类型转换为另一种类型称为类型转换,类型转换总是返回基本类型值,如字符串.数字和布尔值,不会返回引用类型值. 类型转换分为"显式"和"隐式":"显式"转换发生在静态类型语言的编译阶段,而"隐式"转换则发生在动态类型语言的运行时. 显式类型转换 非字符串到字符串的类型转换 toString() 方法 数字.布尔值.字符串和对象都有 toString() 方法,但 null 和 undefined 没有. 例子:

  • 从表单校验看JavaScript策略模式的使用详解

    众所周知的是,表单确实在前端,唔,或者说在网页中占有不小的比重.事实上,几乎每一个中大型网站都会有"登录注册"以验证用户信息.防止一些不可名状的隐患... 那么表单的优劣就成了前端开发者急需解决的问题.其实我更愿意称为"代码的可读性"或"可复用性"以及"是否冗杂". 表单也有"优劣"?你在开玩笑嘛? 我想你可以认真看下下面的代码,它用到了一些"新知识": <form action=

  • 关于Javascript闭包与应用的详解

    前言 Javascript闭包在学习过程中一般较难理解,本文从什么是闭包,常见闭包示例,闭包作用,闭包应用及闭包问题等方面来介绍闭包,希望能给大家带来更深层次的认识,有不恰当之处请指出,谢谢. 一.什么是闭包? 闭包是指一个嵌套的内部(子)函数引用了父函数作用域中数据的函数,这就产生了闭包. 关键理解: 1. 产生闭包必须要有嵌套函数 2. 闭包是函数,并是嵌套的内部函数 3. 闭包内部函数必须要引用父函数作用域中数据 如果不满足以上条件,则不能产生闭包,接下来示例说明. 1.1闭包满足条件代码

  • JavaScript中BOM和DOM详解

    目录 BOM(浏览器对象模型) 1. window 获取浏览器c窗口尺寸 2. screen 获取电脑屏幕大小 3. window 开启关闭窗口 4. 浏览器事件 5. location 6. history 7. navigator 获取浏览器相关信息 8. 弹窗 DOM (文档对象模型) DOM 分类 DOM对象 Document文档对象 element文档对象 DOM事件操作 鼠标事件 键盘事件 触屏事件 特殊事件 表单事件 浏览器兼容处理 兼容性写法,封装工具 BOM(浏览器对象模型)

随机推荐