Posted in

axios 中的那些天才代码!看完我实力大涨! – 掘金_AI阅读总结 — 包阅AI

包阅导读总结

1.

关键词:axios、调用方式、原理简析、天才想法、源码实现

2.

总结:本文主要介绍了 axios 的两种调用方式,通过手写简单的 axios 代码来理解其原理,分析了 axios 既能 `axios(config)` 又能 `axios.get()` 的天才想法及源码实现,并指出修改 `this` 指向的原因。

3.

主要内容:

– axios 的两种常见调用方式

– `axios({method: ‘post’, url: ‘/user/12345’})`

– `axios.post(‘/user/12345’)`

– 原理简析

– 创建 `Axios` 构造函数

– 在原型上添加方法,如 `request`、`get`、`post`

– 创建实例对象 `aixos`

– 天才想法

– 通过 `createInstance` 函数返回实例,使 `axios` 既能作为函数 `axios(config)` 调用,又能作为对象使用其方法如 `axios.get()`

– 源码实现

– `createInstance` 函数的详细实现

– 解释为何修改 `Axios.prototype.request` 的 `this` 指向

思维导图:

文章地址:https://juejin.cn/post/7387029190620184611

文章来源:juejin.cn

作者:石小石Orz

发布时间:2024/7/3 10:56

语言:中文

总字数:1629字

预计阅读时间:7分钟

评分:91分

标签:axios,JavaScript,HTTP 请求,源码解析,构造函数


以下为原文内容

本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com

精彩新文章:# 拿客户电脑,半小时完成轮播组件开发!被公司奖励500

axios的两种调用方式

经常调接口的同学一定非常熟悉aixos下面的两种使用方式:

axios({  method: 'post',  url: '/user/12345',});
axios.post('/user/12345')

不知道各位大佬有没有思考过这样的问题:

axios到底是个什么东西?我们为什么可以使用这两种方式请求接口呢?axios是怎么设计的?

axios原理简析

为了搞明白上面的问题,我们先按照传统思路仿照axios源码实现一个简单的axios。

手写一个简单的axios

创建一个构造函数

function Axios(config){   this.defaults = config;          this.interceptors = {               request:{},      response:{}  }}

上面的代码中,我们实现了一个基本的Axios类,但它还不具备任何功能。我们现在给它添加功能。

原型上添加方法

Axios.prototype.request = function(config){        console.log('发送Ajax 请求 type:' +config.method)}Axios.prototype.get = function(){        return this.request({method:'GET'})}Axios.prototype.post = function(){        return this.request({method: 'POST'})}

上面的代码中,我们在request属性上创建了一个通用的接口请求方法,get和post实际都调用了request,但内部传递了不同的参数,这和axios(config)、axios.post()有异曲同工之妙。

参考aixos的用法, 现在,我们需要创建实例对象

let aixos = new Axios(config)  

创建后的axios包含defaultsinterceptors属性,其对象原型__proto__上(指向Axios的prototype)包含request、get及post方法,因此,我们现在可以使用aixos.post()的方法模拟调用接口了。

但注意,此时aixos只是一个实例对象,不是一个函数!我们似乎也没办法做到改造代码使用aixos(config)的形式调用接口!

aixos是如何实现的呢?

aixos中的天才想法

为了即能使用axios(config)又能使用axios.get(),axios的核心伪逻辑如下

function Axios(config){   this.defaults = config;          this.interceptors = {               request:{},      response:{}  }}Axios.prototype.request = function(config){        console.log('发送Ajax 请求 type:' +config.method)}Axios.prototype.get = function(){        return this.request({method:'GET'})}Axios.prototype.post = function(){        return this.request({method: 'POST'})}function createInstance(config) {      const instance = Axios.prototype.request;    instance.get = Axios.prototype.get   instance.post = Axios.prototype.post   return instance; }let axios = createInstance();

通过上述的伪代码,我们可以知道axios是createInstance()函数的返回值instance

  • instance 是一个函数,因此,axios也是一个函数,可以使用axios(config);
  • instance也是一个对象(js万物皆对象),其原型上有get方法和post方法,因此,我们可以使用axios.post()。

我们看看aixos的源码

aixos的源码实现

 function createInstance(config) {      var context = new Axios(config);       var instance = Axios.prototype.request.bind(context);         Object.keys(Axios.prototype).forEach(key => {          instance[key] = Axios.prototype[key].bind(context);   })               Object.keys(context).forEach(key => {     instance[key] = context[key];   })   return instance; }

可以说,上面的代码真的写的精妙绝伦啊!

注意这里,为什么要修改this的指向

var instance = Axios.prototype.request.bind(context);

首先,requset 是Axios原型对象上的方法,其方法内部的this指向的是其实例化对象context!

Axios.prototype.request = function request(config) {      if (typeof config === 'string') {    config = arguments[1] || {};    config.url = arguments[0];  } else {    config = config || {};  }  config = mergeConfig(this.defaults, config);    if (config.method) {    config.method = config.method.toLowerCase();  } else if (this.defaults.method) {    config.method = this.defaults.method.toLowerCase();  } else {    config.method = 'get';  }    var chain = [dispatchRequest, undefined];  var promise = Promise.resolve(config);  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {    chain.unshift(interceptor.fulfilled, interceptor.rejected);  });  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {    chain.push(interceptor.fulfilled, interceptor.rejected);  });  while (chain.length) {    promise = promise.then(chain.shift(), chain.shift());  }  return promise;};

因此,如果我们直接使用Axios.prototype.request()就会出现问题,因为这事reques方法内部的this会指向错误,导致函数不能运行,因此,我们必须将this重新指向其实例化对象。