01
前言
众所周知在前后分离的背景下,一款优秀的网络请求库是多么的重要,axios 现在几乎已经是一个项目开发的标配了,无论是从vue 还是到 react 都可以看到它的身影。可以看出这个库的受欢迎程度。
这两篇文章我们看一下 axios 的相关知识。从 import axios from 'axios' 再到 axios 的内部源码,带大家看一下经典库的运行流程。
相信大家认真读完之后肯定会有所收获。
为了能帮助更多人学习,如果有需要的可以加我的好友邀请你进入前端学习交流微信群。
02
功能概览
以下内容来自 axios 官方
- Make XMLHttpRequests from the browser
- Make http requests from node.js
- Supports the Promise API
- Intercept request and response
- Transform request and response data
- Cancel requests
- Automatic transforms for JSON data
- Client side support for protecting against XSRF
03
**基本使用及问题思考
**
这里我们假定您已经创建好了一个项目并且成功引入了 axios 依赖。
下面我们看一下在使用的 axios的时候一些步骤:
1、引入 axios 如下:
import axios from 'axios'
这行代码背后做了什么?
我们稍后再来说
2、使用 axios
// 使用方式一
axios({
url: xxxx,
data: {}
}).then(res => {})
// 使用方式二
axios.[get|post|put]({
url: xxxx,
data: {}
}).then(res => {})
// 使用方式三
axios.request({
url: xxxx,
data: {}
}).then(res => {})
从上面的代码可以看出 axios 的使用方式可以说是有很多种,而且配置也比较完善,我们引入的 axios 即可以直接调用,又可以以对象的方式调用其它方法。
那么axios到底是怎么做到的?稍后我们也会进行讲解。
3、最后再来看一下我个人认为 axios 最优秀的地方,执行链、拦截器是怎么运行的,运行的流程是是怎么样的。
下面我们一一解答,可以本篇文件讲解不完,我会分成两篇文章进行说明。
04
**import axios from 'axios'背后做了什么
**
要了解这个问题,首先要知道 js 模块化背后做了什么。
我们平时安装的一些第三方依赖库在我们 npm i 或者 npm install 之后都会被放到项目的 node_modules 文件夹下面。里面的内容是非常非常多的,因为不仅仅是我们项目所需要依赖,还有依赖所需要依赖……直到把所有的依赖都加载完成之后才算完成。
当打包工具执行到 import axios from 'axios' 这行代码之后,他会从 node_modules里面寻找 axios 目录,如果没有则报错:找不到依赖,让你进行安装。
如果已经找到 axios 目录,则会继续找到该目录下面的 package.json 清单文件。内容如下(版本不同,内容可能也会不同,不过大同小异)
在加载完 package.json之后,会找到 "main":"index.js" 这行配置。并且会认定 "index.js" 为入口文件。执行里面的代码,如下:
从上面代码可以看出,最后又加加载执行 ./lib/axios
文件中的代码。在加载 文件中的代码时会找到默认导出,如下:
至些,我们 import axios from 'axios' 背后的基本操作说完了,最后找到了
'/lib/axios'中的 module.exports = axios 这行代码,拿到 axios 实例。
05
axios实例倒底是什么
从上面我们简单的分析出 import axios from 'axios' 获取实例的过程。然后就开始使用,但是有些朋友会有疑问,为什么 axios 即能当方法调用也可以当对象调用其方法属性,非常灵活也非常方便。这背后是怎么做的?我们继续分析
lib/axios
文件中暴露出一个默认的实例对象 axios
。如下:
module.exports = axios;
看一下这个对象的定义:
// Create the default instance to be exported
var axios = createInstance(defaults);
是由一个方法生成,继续看这个 createInstance
函数
function createInstance(defaultConfig) {
var context = new Axios(defaultConfig);
var instance = bind(Axios.prototype.request, context);
// Copy axios.prototype to instance
utils.extend(instance, Axios.prototype, context);
// Copy context to instance
utils.extend(instance, context);
return instance;
}
我们重点看一下:
var instance = bind(Axios.prototype.request, context);
instance实例由bind函数返回,bind函数内容如下:
module.exports = function bind(fn, thisArg) {
return function wrap() {
var args = new Array(arguments.length);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}
return fn.apply(thisArg, args);
};
};
到这里我们就应该能看明白 bind 函数返回了一个名字叫 wrap的函数。也就是说上面的 instance 其实就是一个 函数,这样一步步的返回最终 lib/axios 默认导出的就是一个函数类型的数据。
这也就说明了为什么 import axios from 'axios' 之后 我们可以直接当函数进行调用。因为默认的 axios 本身就是函数肯定可以直接调用。
那问题又来了,为什么 axios 还可以当成对象那样可以调用某些属性方法呢?
那就要看下 createInstance函数中的两行行代码了:
// Copy axios.prototype to instance
utils.extend(instance, Axios.prototype, context);
// Copy context to instance
utils.extend(instance, context);
这里涉及到了原型链的一些知识。可以理解成把 Axios.prototype 中的方法分配给了 instance 函数对象中,具体的过程如下:
function extend(a, b, thisArg) {
forEach(b, function assignValue(val, key) {
if (thisArg && typeof val === 'function') {
a[key] = bind(val, thisArg);
} else {
a[key] = val;
}
});
return a;
}
被分配方法有:
['post', 'put', 'patch']
['delete', 'get', 'head', 'options']
['request', 'getUri']
所以我们就可以像:axios.get 或者 axios.post 这样调用了。
到目录为止我们基本已经梳理清楚了axios的加载过程,和基本的用法。
-
内部
+关注
关注
0文章
9浏览量
18851 -
运行
+关注
关注
0文章
25浏览量
15399 -
源码
+关注
关注
8文章
639浏览量
29184
发布评论请先 登录
相关推荐
评论