Article directory
The current chapter officially enters the handwritten axios source code series, and we have to start writing code with real guns.
Because the axios source code has a relatively large amount of code, we only focus on the main thread here to give everyone a general understanding of the main core functions of axios. As for the specific details, you need to read through the axios source code to understand. The handwritten axios source code series only handwrites 4 of the main functional modules, which is in the previous article: Handwritten axios source code series one: axios core knowledge points The four core function points introduced in:
- axios function object
- dispatchRequest sends a request
- interceptors interceptors
- cancelToken cancel request
1. Introduction to modular catalog
It is recommended that you download the source code of axios first, and then go through the directory files of the source code. The main files are all in the lib
directory. I will not introduce them one by one here.
Next, let’s take a look at the directory introduction created by my handwritten axios source code (the file name is based on the name of the source code file):
- _Axios.js: The constructor of axios. Because there is one axios.js, the file name is not case-sensitive and will be repeated, so a underscore is added< a i=2> Prevent file name duplication; among them, request method is the focus, interceptor function< a i=6>Write here;
_Axios
- adapters.js: Adapter, which has a method
getAdapter
to get the method of sending the request xhr or http; - axios.js: The entry file of the entire directory, creates the axios function object and exposes some properties and methods to the outside world;
- CancelToken: function code to cancel the request;
- defaults.js: Default configuration items (preconfigured);
- dispatchRequest.js: The file directory where the request is actually sent and the response data is received;
- index.html: Handwritten test code of axios source code to test whether the code you wrote is correct;
- InterceptorManager: constructor of the interceptor;
- xhr.js: File directory for writing AJAX (Asynchronous Javascript And XML) code.
2. Create axios function object
1. Create axios.js file
import Axios from "./_Axios.js";
import defaults from "./defaults.js";
import CancelToken from "./CancelToken";
// 初始化 axios 函数对象
function createInstance(defaultConfig){
// 生成 _Aixos 的实例对象
const context = new Axios(defaultConfig);
// 生成 instance 绑定函数,并且绑定 this 为 context,防止调用时 this 指向不明
const instance = Axios.prototype.request.bind(context, ...arguments);
// 将 context 实例对象的属性复制到 instance 上
Object.keys(context).forEach(key=>{
instance[key] = context[key]
})
// 将 Axios 原型对象的属性复制到 instance 上
Object.keys(Axios.prototype).forEach(key=>{
instance[key] = Axios.prototype[key]
})
// axios.create 方法
instance.create = function(instanceConfig){
const mergeConfig = {
...defaultConfig,
...instanceConfig
}
return createInstance(mergeConfig);
}
// instance 就是 axios
return instance;
}
// 创建 axios 函数对象
const axios = createInstance(defaults);
// 对外暴露 CancelToken 类,取消请求时使用
axios.CancelToken = CancelToken;
// 导出 axios
export default axios;
2. Create defaults.js file
export default {
// 适配器的默认配置,写适配器 adapters 代码时需要传入的配置
adapter: ['xhr', 'http']
}
3. Create the _Axios.js file
import InterceptorManager from "./IntercptorManager.js";
import dispatchRequest from "./dispatchRequest.js";
export default class Axios {
constructor(config){
// 实例对象的 defaults属性(默认配置对象)
this.defaults = config;
// 实例对象的 interceptors属性(拦截器)
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
}
}
// request 发送请求
request(configOrUrl, config){
// 判断 configOrUrl是否为 url地址
if(typeof configOrUrl === "string"){
config.url = configOrUrl
} else {
config = {
...configOrUrl,
...config
}
}
// 将 config包装为一个成功状态的 promise对象
let promise = Promise.resolve(config);
// 创建执行链,这里调用 dispatchRequest方法以发送请求
const chain = [dispatchRequest, undefined];
// 调用 promise.then()将 config传入 dispatchRequest中,dispatchRequest中返回的也是一个 prommise对象
promise = promise.then(chain[0], chain[1]);
// 发送请求后返回的是一个 promise对象
return promise;
}
}
const methodsWithNoData = ["delete", "get", "head", "options"];
const methodsWithData = ["post", "put", "patch"];
// 给 Axios的原型对象添加请求方法
methodsWithNoData.forEach(method => {
Axios.prototype[method] = function(url, config){
config = {
...config, method, url };
// 最后返回 request生成的 promise对象
return this.request(config)
}
})
methodsWithData.forEach(method => {
Axios.prototype[method] = function(url, data, config){
config = {
...config, method, url, data };
return this.request(config)
}
})
4. Summary
The above code contains the creation process of axios function object:
- Use
createInstance()
to generate axios function object- First instantiate the object context, and then use the Axios.prototype.request method to bind a new function instance. Calling
instance()
is equivalent to callingAxios.prototype.request()
;< /span> - The generated new function instance does not have any properties and methods to use, so the properties and methods on context and Axios.prototype are copied to the instance for use;
- mounts a create method for use by axios packaging. Calling the
create()
method is actually calling thecreateInstance()
method.
- First instantiate the object context, and then use the Axios.prototype.request method to bind a new function instance. Calling
- Mount other properties for axios and expose them for external use.
- Export axios function object.
In the next article we will focus on dispatchRequest and adapter adapters.