Мы не будем здесь представлять Axios, мы сразу перейдем к теме и проанализируем исходный код из базового запроса на получение.
axios.get('/get?name=xmz')
.then((response)=>{
console.log('response', response)
})
.catch((error)=>{
console.log('error', error)
})
Давайте сначала посмотрим на объект axios. На данный момент я думаю, что это обычный объект. После загрузки файла axios его можно использовать напрямую, поэтому я иду прямо к файлу, чтобы найти его ~~~
оказатьсяaxios/lib/axios.js
Я прямо увидел, где лежит var axios.
var axios = createInstance(defaults);
Независимо от значений по умолчанию, это объект по умолчанию, и вы можете увидеть метод createInstance при поиске.
function createInstance(defaultConfig){
var context = new Axios(defaultConfig);
//new Axios()这么说context 是一个对象了
var instance = bind(Axios.prototype.request, context);
//bind()要对这个对象干什么???
//...下面的就先不看了
return instance;
}
Затем потяните дальнюю точку, чтобы увидеть метод привязки контекста, в конце концов, что делать? определение привязкиaxios/lib/helps/bind.js
в этом каталоге
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 возвращает перенос функции.Не глядя на слова внутри, мы можем знать, что экземпляр является функцией, а затем, когда экземпляр выполняется, он фактически выполняет Axios.proptotype.request, это указывает на контекст, грубо говоря, связывание чтобы изменить эту точку Ну, возврат функции createInstance — это экземпляр, поэтому axios — это экземпляр, который является функцией.
Поскольку axios — это функция, где определен атрибут get этой функции? Тогда я в целомaxios/lib
Я просто и грубо искал axios.get в папке, но не нашел~~~
долго не мог найти! ! Сходить с ума! ! Но когда я пролистываю исходный код, я вижу, что в Axios.prototype есть атрибут get, но axios не является инстанцированным объектом Axios, что мне делать?
В это время обнаружилось, что после var axios у axios уже был атрибут get (написал for в цикле и тайно посмотрел на него), потом я проследил и нашел метод createInstance.
function createInstance(){
//...
//刚才有两行省略掉没看 好后悔!
//看到extend 好激动
utils.extend(instance, Axios.prototype, context);
utils.extend(instance, context)
return instance
}
Теперь я знаю, что свойство get axios изначально унаследовано от Axios.prototype, так что давайте посмотрим, как работает utils.entend! попал внутрьaxios/lib/util.js
документ.
function extend(a, b, thisArg){
// extend就是把b的属性都复制个a
forEach(b, function(value, key){
//如果属性的值是一个方法的话,就改变this的指向到thisArg再复制给a
if(thisArg && typeof value == 'function'){
a[key] = bind(val, thisArg)
}else{
a[key] = value;
}
})
return a
}
axios наследует все атрибуты Axios.prototype и контекст, а значение свойства — это метод, то это точка, к которой относится контекст.
На этот раз вы можете увидеть Axios.prototype.get и не искать, я вижу, что он не определен напрямую в файле! Хахаха! существуетaxios/lib/core/Axios.js
внутри
utils.forEach(['delete', 'get', 'head', 'option'], function(method){
Axios.proptotype[method] = function(url, config){
// 先不去看util.merge了,我猜也就是把config 和 后面的对象进行下合并
return this.request(util.merge(config||{}, {
method: method,
url: url
}))
}
})
Axios.prototype.get() на самом деле выполняет Axios.prototype.request(), который все еще находится в этом файле, посмотрите
Axios.prototype.request = function request(config){
// ...
// 开始就对config进行判断,合并默认配置
var chain = [dispatchRequest, undefined]
// dispatchRequest是什么一会再说
var promise = Promise.resolve(config)
// Promise.resolve一个对象,promise就是一个立即resolve的Promise对象
// ...
// 关于interceptors拦截器的东西先不看了
while(chain.length){
promise = promise.then(chain.shift(), chain.shift())
}
return promise
}
Возвращается обещание, которое соответствует axios.get('/get?name=xmz').then().catch(). Независимо от перехватчика, после этого цикла while фактически выполняется диспетчерский запрос (конфигурация), затем перейдите кaxios/lib/core/dispatchRequest.js
посмотри
function dispatchRequest(config){
// ...
// 开始就对config的 baseUrl, data, headers进行处理
var adapter = config.adapter || defaults.adapter;
// 这个adapter是什么?一路以来并没有关注啊?
// 执行adapter是一个Promise对象,resolve的函数的参数还是response
// adpater肯定是去发送请求了啊
return adapter(config).then(function(response){
// ...
return response
}, function(reason){
// ...
return Promise.reject(reason)
})
}
Поскольку config.adapter его не видит, перейдите кaxios/lib/default.js
Посмотрите на defaults.adapter
var defaults.adapter = getDefaultAdapter();
function getDefaultAdapter(){
var adapter;
if(typeof XMLHttpRequest !== 'undefined'){
// 浏览器环境
adapter = require('./adapter/xhr');
}else if(typeof process !== 'undefined'){
// node环境
adapter = require('./adapter/http');
}
return adapter;
}
Адаптер должен различать браузер и среду узла, тогда мы идемaxios/lib/adapter/xhr.js
Давайте взглянем на среду браузера, то есть она инкапсулирует обещание сделать сервер запросов ajax, поэтому я не буду его здесь рассматривать.
Давайте вернемся и посмотрим на запрос на получение в начале.Axios.get наследуется от Axios.prototype.get.На самом деле он выполняет Axios.prototype.request и возвращает объект обещания, так что вы можете использовать then и catch для получения возвращаемое значение и обработка ошибок. Основной функцией для выполнения ajax-запросов является адаптер, который различает браузер и среду узла.
Что ж, если не обращать внимания на различные детали, весь процесс вполне ясен!
Xiaobai впервые анализирует исходный код, с этим можно обойтись!
Что касается анализа перехватчиков,Портал, нажмите здесь.
Анализ запросов на отмену,Портал, нажмите здесь.