1. Введение
Здравствуйте, яВакагава. Это
学习源码整体架构系列
Шестой Слово «общая архитектура» кажется немного большим, скажем так, это общая структура исходного кода. В этой статье изучается код фактического склада.
学习源码整体架构系列
Статья выглядит следующим образом:
1.Изучите общую архитектуру исходного кода jQuery и создайте собственную библиотеку js.
2.Изучите общую архитектуру исходного кода подчеркивания и создайте собственную библиотеку классов функционального программирования.
3.Изучите общую архитектуру исходного кода lodash и создайте собственную библиотеку классов функционального программирования.
4.Изучите общую архитектуру исходного кода sentry и создайте собственный SDK для мониторинга исключений переднего плана.
5.Изучите общую архитектуру исходного кода vuex и создайте собственную библиотеку управления состоянием.
6.Изучите общую архитектуру исходного кода axios и создайте собственную библиотеку запросов.
7.Изучите общую архитектуру исходного кода koa, проанализируйте принцип луковой модели koa и принцип совместной работы.
8.Изучите общую архитектуру исходного кода Redux и глубоко поймите принципы Redux и его промежуточного программного обеспечения.
Заинтересованные читатели могут нажать, чтобы прочитать. Следующий может бытьvue-router
исходный код.
Эта статья относительно длинная, чтобы читать ее на мобильном телефоне, вы можете прямо посмотреть на несколько картинок в статье. Рекомендуется поставить лайк или добавить в закладки и прочитать на компьютере, может быть проще будет усвоить и переварить самостоятельно, отлаживая по способу отладки в статье.
Управляемое чтение
Подробности статьиaxios
Метод отладки. подробныйaxios
Реализация таких функций, как конструкторы, перехватчики, отмены и т. д. Наконец, сравниваются другие библиотеки запросов.
Версия, изучаемая в этой статье,v0.19.0
. Клон официального репозиторияmaster
ветвь.
На данный момент (14 декабря 2019 г.), последнийcommit
да2019-12-09 15:52 ZhaoXC
dc4bc49673943e352
,fix: fix ignore set withCredentials false (#2582)
.
Этот репозиторий статей находится здесьGitHub-репозиторий аксиального анализа Вакагавы. спроситьstar
Ах.
Если вы ищете работу, проект написан и используетсяaxios
, интервьюер может спросить вас:
1. Почему
axios
Его можно использовать как в качестве вызова функции, так и в качестве объекта, напримерaxios({})
,axios.get
.
2. Краткое описаниеaxios
процесс вызова.
3. Вы когда-нибудь использовали перехватчик? Каков принцип?
4. Используйтеaxios
функция отмены? Как это достигается?
5. Почему он поддерживает отправку запросов в браузерах?node
послать запрос?
Такие вопросы.
2. Метод исходного кода axios для отладки Chrome и vscode
Не так давно автор ответил на вопрос по ЖихуЧто, если фронтенд в течение года не сможет понять исходный код фронтенд-фреймворка?Некоторые материалы рекомендованы, да и объем чтения неплохой, если интересно, можете глянуть. Есть четыре основных момента:
1. С помощью отладки
2. Найдите релевантные статьи с высокой репутацией
3. Запишите то, что вы не понимаете, и сверьтесь с соответствующими документами.
4. Резюме
Глядя на исходный код, отладка очень важна, поэтому автор подробно описал ее.axios
Метод отладки исходного кода, чтобы помочь некоторым читателям, которые могут не знать, как отлаживать.
2.1 Chrome для отладки среды браузера axios
Метод отладки
axios
После упаковкиsourcemap
документ.
# 可以克隆笔者的这个仓库代码
git clone https://github.com/lxchuan12/axios-analysis.git
cd axios-analaysis/axios
npm install
npm start
# open [http://localhost:3000](http://localhost:3000)
# chrome F12 source 控制面板 webpack// . lib 目录下,根据情况自行断点调试
Эта статья через приведенный выше примерaxios/sandbox/client.html
для отладки.
Кстати, краткое упоминание об отладкеexample
Например, хотя эта часть была написана в начале статьи, но потом она была удалена, и, наконец, я подумал и записал.
Найти файлaxios/examples/server.js
, измените код следующим образом:
server = http.createServer(function (req, res) {
var url = req.url;
// 调试 examples
console.log(url);
// Process axios itself
if (/axios\.min\.js$/.test(url)) {
// 原来的代码 是 axios.min.js
// pipeFileToResponse(res, '../dist/axios.min.js', 'text/javascript');
pipeFileToResponse(res, '../dist/axios.js', 'text/javascript');
return;
}
// 原来的代码 是 axios.min.map
// if (/axios\.min.map$/.test(url)) {
if (/axios\.map$/.test(url)) {
// 原来的代码 是 axios.min.map
// pipeFileToResponse(res, '../dist/axios.min.map', 'text/javascript');
pipeFileToResponse(res, '../dist/axios.map', 'text/javascript');
return;
}
}
# 上述安装好依赖后
# npm run examples 不能同时开启,默认都是3000端口
# 可以指定端口 5000
# npm run examples === node ./examples/server.js
node ./examples/server.js -p 5000
Открытьhttp://localhost:5000, и тогда вы можете быть счастливы вChrome
Отладка в браузереexamples
пример в.
axios
да поддержкаnode
Среда отправила запрос. Далее посмотрим, как использоватьvscode
отладкаnode
окружающая обстановкаaxios
.
2.2 Отладочные аксиомы vscode в среде узла
в корневом каталогеaxios-analysis/
Создайте.vscode/launch.json
Файлы следующие:
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/axios/sandbox/client.js",
"skipFiles": [
"<node_internals>/**"
]
},
]
}
согласно сF5
Просто начните отладку и шаг за шагом в соответствии с вашей ситуацией.(F10)
, одношаговая отладка(F11)
Отладка точки останова.
На самом деле проекты с открытым исходным кодом обычно имеют правила участия.axios/CONTRIBUTING.md
, автор только что изменил основу этого руководства, чтобы ссылатьсяsourcemap
файл отлаживаемый.
3. Сначала посмотрите на структуру аксиом
git clone https://github.com/lxchuan12/axios-analysis.git
cd axios-analaysis/axios
npm install
npm start
В соответствии с упомянутым выше методом отладки,npm start
, прямо вchrome
Отладка в браузере.
Открытьhttp://localhost:3000, который выводится на консольaxios
, считается, что многие люди не распечатали его.
console.log({axios: axios});
Кликайте по нему слой за слоем,axios
Что такое структура, сначала есть общее впечатление.
Автор нарисовал более подробную схему.
После прочтения структурной схемы, если вы виделиjQuery
,underscore
а такжеlodash
исходный код, вы обнаружите, что он на самом деле такой же, какaxios
Дизайн исходного кода аналогичен.
jQuery
псевдоним$
,underscore
loadsh
псевдоним_
Это и функция, и объект. НапримерjQuery
Как использовать.$('#id')
, $.ajax
.
Далее посмотрите на реализацию конкретного исходного кода. Вы можете следовать точке останова для отладки.
Советы по отладке точки останова:
Оператор присваивания можно пропустить за один шаг, просто посмотрите на возвращаемое значение, а позже подробно изучите его.
Выполнение функции требует точек останова, и вы также можете использовать комментарии и контекст, чтобы отодвигать то, что делает функция.
4. Инициализация исходного кода axios
Посмотрите на исходный код Первый шаг, посмотрите сначалаpackage.json
. обычно заявляютmain
основной входной файл.
// package.json
{
"name": "axios",
"version": "0.19.0",
"description": "Promise based HTTP client for the browser and node.js",
"main": "index.js",
// ...
}
основной входной файл
// index.js
module.exports = require('./lib/axios');
4.1 lib/axios.js
основной файл
axios.js
Код файла относительно больше. Разверните повествование, разделив его на три части.
- Часть 1. Знакомство с некоторыми служебными функциями
utils
,Axios
Конструктор, конфигурация по умолчаниюdefaults
Ждать.
- Вторая часть: генерировать экземпляры объектов
axios
,axios.Axios
,axios.create
Ждать.
- Третья часть отменяет соответствующую реализацию API и
all
,spread
, экспорт и т.д.
4.1.1 Часть 1
Ввести некоторые полезные функцииutils
,Axios
Конструктор, конфигурация по умолчаниюdefaults
Ждать.
// 第一部分:
// lib/axios
// 严格模式
'use strict';
// 引入 utils 对象,有很多工具方法。
var utils = require('./utils');
// 引入 bind 方法
var bind = require('./helpers/bind');
// 核心构造函数 Axios
var Axios = require('./core/Axios');
// 合并配置方法
var mergeConfig = require('./core/mergeConfig');
// 引入默认配置
var defaults = require('./defaults');
4.1.2 Часть II
заключается в создании экземпляра объектаaxios
,axios.Axios
,axios.create
Ждать.
/**
* Create an instance of Axios
*
* @param {Object} defaultConfig The default config for the instance
* @return {Axios} A new instance of Axios
*/
function createInstance(defaultConfig) {
// new 一个 Axios 生成实例对象
var context = new Axios(defaultConfig);
// bind 返回一个新的 wrap 函数,
// 也就是为什么调用 axios 是调用 Axios.prototype.request 函数的原因
var instance = bind(Axios.prototype.request, context);
// Copy axios.prototype to instance
// 复制 Axios.prototype 到实例上。
// 也就是为什么 有 axios.get 等别名方法,
// 且调用的是 Axios.prototype.get 等别名方法。
utils.extend(instance, Axios.prototype, context);
// Copy context to instance
// 复制 context 到 intance 实例
// 也就是为什么默认配置 axios.defaults 和拦截器 axios.interceptors 可以使用的原因
// 其实是new Axios().defaults 和 new Axios().interceptors
utils.extend(instance, context);
// 最后返回实例对象,以上代码,在上文的图中都有体现。这时可以仔细看下上图。
return instance;
}
// Create the default instance to be exported
// 导出 创建默认实例
var axios = createInstance(defaults);
// Expose Axios class to allow class inheritance
// 暴露 Axios class 允许 class 继承 也就是可以 new axios.Axios()
// 但 axios 文档中 并没有提到这个,我们平时也用得少。
axios.Axios = Axios;
// Factory for creating new instances
// 工厂模式 创建新的实例 用户可以自定义一些参数
axios.create = function create(instanceConfig) {
return createInstance(mergeConfig(axios.defaults, instanceConfig));
};
Вот краткое описание заводской выкройки.axios.create
То есть пользователю не нужно знать, как он реализован внутри.
Например, когда мы покупаем мобильный телефон, нам не нужно знать, как он сделан, это заводской режим.
После прочтения второй части, есть несколько задействованных функций инструмента, таких какbind
,extend
. Эти инструменты описаны далее.
4.1.3 Привязка метода инструмента
axios/lib/helpers/bind.js
'use strict';
// 返回一个新的函数 wrap
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];
}
// 把 argument 对象放在数组 args 里
return fn.apply(thisArg, args);
};
};
Передача двух аргументов в функцию иthisArg
направление.
Поставить параметрыarguments
Сгенерируйте массив и, наконец, вызовите структуру возвращаемых параметров.
На самом деле сейчасapply
служба поддержкиarguments
Такой подобный массиву объект не нуждается в ручном преобразовании массива.
Так зачем же автор перевернул массив, для производительности? Не поддерживается на данный момент? Или автор не в курсе? Это неизвестно. Знающие читатели могут сообщить об этом автору в комментариях.
оapply
,call
а такжеbind
Для читателей, которые не очень знакомы, вы можете прочитать другие статьи автора.面试官问系列
.
Интервьюер спросил: Могу ли я смоделировать метод привязки, реализующий JS?
Например
function fn(){
console.log.apply(console, arguments);
}
fn(1,2,3,4,5,6, '若川');
// 1 2 3 4 5 6 '若川'
4.1.4 utils.extend метода инструмента
axios/lib/utils.js
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;
}
Фактически, это обход параметровb
объект, скопированный вa
На объекте, если это функция, используйтеbind
передача.
4.1.5 utils.forEach метода инструмента
axios/lib/utils.js
Обход массивов и объектов. Шаблон проектирования называется шаблоном итератора. Многие исходные коды имеют подобные функции обхода. например, известныйjQuery
$.each
.
/**
* @param {Object|Array} obj The object to iterate
* @param {Function} fn The callback to invoke for each item
*/
function forEach(obj, fn) {
// Don't bother if no value provided
// 判断 null 和 undefined 直接返回
if (obj === null || typeof obj === 'undefined') {
return;
}
// Force an array if not already something iterable
// 如果不是对象,放在数组里。
if (typeof obj !== 'object') {
/*eslint no-param-reassign:0*/
obj = [obj];
}
// 是数组 则用for 循环,调用 fn 函数。参数类似 Array.prototype.forEach 的前三个参数。
if (isArray(obj)) {
// Iterate over array values
for (var i = 0, l = obj.length; i < l; i++) {
fn.call(null, obj[i], i, obj);
}
} else {
// Iterate over object keys
// 用 for in 遍历对象,但 for in 会遍历原型链上可遍历的属性。
// 所以用 hasOwnProperty 来过滤自身属性了。
// 其实也可以用Object.keys来遍历,它不遍历原型链上可遍历的属性。
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
fn.call(null, obj[key], key, obj);
}
}
}
}
если правильноObject
СвязанныйAPI
Если вы не знакомы с этим, вы можете проверить статью, которую я написал ранее.Весь API-анализ объектов JavaScript
4.1.6 Часть III
Отмените соответствующие реализации API иall
,spread
, экспорт и т.д.
// Expose Cancel & CancelToken
// 导出 Cancel 和 CancelToken
axios.Cancel = require('./cancel/Cancel');
axios.CancelToken = require('./cancel/CancelToken');
axios.isCancel = require('./cancel/isCancel');
// Expose all/spread
// 导出 all 和 spread API
axios.all = function all(promises) {
return Promise.all(promises);
};
axios.spread = require('./helpers/spread');
module.exports = axios;
// Allow use of default import syntax in TypeScript
// 也就是可以以下方式引入
// import axios from 'axios';
module.exports.default = axios;
Здесьspread
,отменитьAPI
Я пока не буду его анализировать, а подробно разберу позже.
Допустим, у вас есть такая потребность.
function f(x, y, z) {}
var args = [1, 2, 3];
f.apply(null, args);
тогда вы можете использоватьspread
метод. Применение:
axios.spread(function(x, y, z) {})([1, 2, 3]);
Реализация также относительно проста. Реализация исходного кода:
/**
* @param {Function} callback
* @returns {Function}
*/
module.exports = function spread(callback) {
return function wrap(arr) {
return callback.apply(null, arr);
};
};
надvar context = new Axios(defaultConfig);
, за которым следует основной конструкторAxios
.
4.2 Базовый конструктор Axios
axios/lib/core/Axios.js
КонструкторAxios
.
function Axios(instanceConfig) {
// 默认参数
this.defaults = instanceConfig;
// 拦截器 请求和响应拦截器
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
Axios.prototype.request = function(config){
// 省略,这个是核心方法,后文结合例子详细描述
// code ...
var promise = Promise.resolve(config);
// code ...
return promise;
}
// 这是获取 Uri 的函数,这里省略
Axios.prototype.getUri = function(){}
// 提供一些请求方法的别名
// Provide aliases for supported request methods
// 遍历执行
// 也就是为啥我们可以 axios.get 等别名的方式调用,而且调用的是 Axios.prototype.request 方法
// 这个也在上面的 axios 结构图上有所体现。
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
/*eslint func-names:0*/
Axios.prototype[method] = function(url, config) {
return this.request(utils.merge(config || {}, {
method: method,
url: url
}));
};
});
utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
/*eslint func-names:0*/
Axios.prototype[method] = function(url, data, config) {
return this.request(utils.merge(config || {}, {
method: method,
url: url,
data: data
}));
};
});
module.exports = Axios;
Затем посмотрите на раздел перехватчика.
4.3 Конструктор управления перехватчиками InterceptorManager
Перехват до запроса и перехват после запроса.
существуетAxios.prototype.request
Используемая в функции функция, как добиться перехвата, будет подробно описано далее с примерами.
репозиторий axios github документация перехватчика
как использовать:
// Add a request interceptor
// 添加请求前拦截器
axios.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
// 添加请求后拦截器
axios.interceptors.response.use(function (response) {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response;
}, function (error) {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
return Promise.reject(error);
});
Если вы хотите поставить перехватчик, вы можете использоватьeject
метод.
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
Экземпляр перехватчика может быть добавлен к пользователю.
const instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});
Реализация исходного кода:
Конструктор,handles
Используется для хранения функций перехватчика.
function InterceptorManager() {
this.handlers = [];
}
Далее объявляются три метода: use, remove, traverse.
4.3.1 Использование InterceptorManager.prototype.use
Передайте две функции в качестве параметров, один элемент в массиве хранит{fulfilled: function(){}, rejected: function(){}}
. номер возвратаID
Для снятия интерцепторов.
/**
* @param {Function} fulfilled The function to handle `then` for a `Promise`
* @param {Function} rejected The function to handle `reject` for a `Promise`
*
* @return {Number} 返回ID 是为了用 eject 移除
*/
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected
});
return this.handlers.length - 1;
};
4.3.2 InterceptorManager.prototype.eject удален
согласно сuse
вернутьID
Удалите блокировщик.
/**
* @param {Number} id The ID that was returned by `use`
*/
InterceptorManager.prototype.eject = function eject(id) {
if (this.handlers[id]) {
this.handlers[id] = null;
}
};
Что-то вроде таймераsetTimeout
а такжеsetInterval
, возвращаемое значение равноid
. использоватьclearTimeout
а такжеclearInterval
чтобы очистить таймер.
// 提一下 定时器回调函数是可以传参的,返回值 timer 是数字
var timer = setInterval((name) => {
console.log(name);
}, 1000, '若川');
console.log(timer); // 数字 ID
// 在控制台等会再输入执行这句,定时器就被清除了
clearInterval(timer);
4.3.3 InterceptorManager.prototype.forEach Traversal
Перебрать все перехватчики, передать функцию обратного вызова (каждая функция перехватчика в качестве параметра) для вызова, удаленный элементnull
, поэтому он не будет выполнен, а эффект удаления будет достигнут.
/**
* @param {Function} fn The function to call for each interceptor
*/
InterceptorManager.prototype.forEach = function forEach(fn) {
utils.forEach(this.handlers, function forEachHandler(h) {
if (h !== null) {
fn(h);
}
});
};
5. Комбинация экземпляров
Запустите во время отладки, как описано вышеnpm start
используетсяaxios/sandbox/client.html
Файл пути используется в качестве примера, и читатели могут самостоятельно его отладить.
Ниже приведен фрагмент кода из этого файла.
axios(options)
.then(function (res) {
response.innerHTML = JSON.stringify(res.data, null, 2);
})
.catch(function (res) {
response.innerHTML = JSON.stringify(res.data, null, 2);
});
5.1 Первый взгляд на процесс стека вызовов
Если вы не хотите отлаживать шаг за шагом, есть хитрый способ.
знаниеaxios
использовалXMLHttpRequest
.
Вы можете искать в проекте:new XMLHttpRequest
.
Перейти к файлуaxios/lib/adapters/xhr.js
в этом заявленииvar request = new XMLHttpRequest();
chrome
Нажмите точку останова в браузере для отладки, а затем внимательно изучите реализацию определенных функций и других функций в соответствии со стеком вызовов.
Call Stack
dispatchXhrRequest (xhr.js:19)
xhrAdapter (xhr.js:12)
dispatchRequest (dispatchRequest.js:60)
Promise.then (async)
request (Axios.js:54)
wrap (bind.js:10)
submit.onclick ((index):138)
Кратко опишу процесс:
-
Send Request
щелчок кнопкиsubmit.onclick
- передача
axios
функция на самом деле вызываетAxios.prototype.request
функция, и эта функция используетbind
возвращает именованныйwrap
Функция.
- передача
Axios.prototype.request
- (Перехватчик запроса выполняется, когда есть перехватчик запроса), и он будет выполняться в середине
dispatchRequest
метод
-
dispatchRequest
звонить послеadapter (xhrAdapter)
- последний звонок
Promise
функционировать вdispatchXhrRequest
, (если есть перехватчик ответа, то перехватчик ответа будет вызван в конце)
Если вы внимательно прочитали статью,axios 结构关系图
, по сути, имеют общее представление об этом процессе.
см. далееAxios.prototype.request
Реализация.
5.2 Основной метод запроса Axios.prototype.request
Эта функция является основной функцией. Делайте в основном следующие вещи:
1. Судя по тому, что первый параметр — это строка, задаем url, т. е. поддержку
axios('example/url', [, config])
, также поддерживаетaxios({})
.
2. Объедините параметры по умолчанию и параметры, переданные пользователем
3. Установите метод запроса, по умолчанию даget
метод
4. Установите перехватчики запроса и ответа, установленные пользователем, и отправьте запросdispatchRequest
сочинениеPromise
цепь, окончательный возврат по-прежнемуPromise
пример.
也就是保证了请求前拦截器先执行,然后发送请求,再响应拦截器执行这样的顺序。<br>
也就是为啥最后还是可以`then`,`catch`方法的缘故。<br>
Axios.prototype.request = function request(config) {
/*eslint no-param-reassign:0*/
// Allow for axios('example/url'[, config]) a la fetch API
// 这一段代码 其实就是 使 axios('example/url', [, config])
// config 参数可以省略
if (typeof config === 'string') {
config = arguments[1] || {};
config.url = arguments[0];
} else {
config = config || {};
}
// 合并默认参数和用户传递的参数
config = mergeConfig(this.defaults, config);
// Set config.method
// 设置 请求方法,默认 get 。
if (config.method) {
config.method = config.method.toLowerCase();
} else if (this.defaults.method) {
config.method = this.defaults.method.toLowerCase();
} else {
config.method = 'get';
}
// Hook up interceptors middleware
// 组成`Promise`链 这段拆开到后文再讲述
};
5.2.1 СоставPromise
цепь, возвратPromise
Пример
Эта часть: перехватчики запроса и ответа, установленные пользователем, тот, который отправляет запрос
dispatchRequest
сочинениеPromise
цепь. Другими словами, он гарантирует, что перехватчик выполняется сначала перед запросом, затем отправляется запрос, а затем выполняется перехватчик ответа в этом порядке.
也就是保证了请求前拦截器先执行,然后发送请求,再响应拦截器执行这样的顺序<br>
也就是为啥最后还是可以`then`,`catch`方法的缘故。<br>
Если читательPromise
Если вы не знакомы с ним, рекомендуется прочитать книгу Учителя Руана «Введение в стандарты ES6».Обещание-решение ES6 Руана Ифэнаа такжеМини-книга обещаний JavaScript (китайская версия)
// 组成`Promise`链
// Hook up interceptors middleware
// 把 xhr 请求 的 dispatchRequest 和 undefined 放在一个数组里
var chain = [dispatchRequest, undefined];
// 创建 Promise 实例
var promise = Promise.resolve(config);
// 遍历用户设置的请求拦截器 放到数组的 chain 前面
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});
// 遍历用户设置的响应拦截器 放到数组的 chain 后面
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
chain.push(interceptor.fulfilled, interceptor.rejected);
});
// 遍历 chain 数组,直到遍历 chain.length 为 0
while (chain.length) {
// 两两对应移出来 放到 then 的两个参数里。
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
var promise = Promise.resolve(config);
Объясните это предложение. функция состоит в том, чтобы генерироватьPromise
пример.
var promise = Promise.resolve({name: '若川'})
// 等价于
// new Promise(resolve => resolve({name: '若川'}))
promise.then(function (config){
console.log(config)
});
// {name: "若川"}
Также объясните, что появится позжеPromise.reject(error);
:
Promise.reject(error);
var promise = Promise.reject({name: '若川'})
// 等价于
// new Promise(reject => reject({name: '若川'}))
// promise.then(null, function (config){
// console.log(config)
// });
// 等价于
promise.catch(function (config){
console.log(config)
});
// {name: "若川"}
Затем объедините пример, чтобы понять этот код.
К сожалению, вexample
Папки не имеют примера перехватчиков. Автор находится вexample
в серединеexample/get
Пример перехватчика добавлен поверх .axios/examples/interceptors
, который читателям удобно отлаживать.
node ./examples/server.js -p 5000
promise = promise.then(chain.shift(), chain.shift());
Этот код достигает точки останова.
Вы получите эту картину.
Особое внимание справа,local
серединаchain
множество. Это структура.
var chain = [
'请求成功拦截2', '请求失败拦截2',
'请求成功拦截1', '请求失败拦截1',
dispatch, undefined,
'响应成功拦截1', '响应失败拦截1',
'响应成功拦截2', '响应失败拦截2',
]
Этот код относительно запутан. То есть будет сгенерирован код, подобный следующему, который будет вызываться в серединеdispatchRequest
метод.
// config 是 用户配置和默认配置合并的
var promise = Promise.resolve(config);
promise.then('请求成功拦截2', '请求失败拦截2')
.then('请求成功拦截1', '请求失败拦截1')
.then(dispatchRequest, undefined)
.then('响应成功拦截1', '响应失败拦截1')
.then('响应成功拦截2', '响应失败拦截2')
.then('用户写的业务处理函数')
.catch('用户写的报错业务处理函数');
упомянуть здесьpromise
then
а такжеcatch
Знание:
Promise.prototype.then
Первый параметр методаresolved
Функция обратного вызова состояния, второй параметр (необязательный)rejected
Функция обратного вызова статуса. Так что это идет парами.
Promise.prototype.catch
путь.then(null, rejection)
или.then(undefined, rejection)
Псевдоним для указания функции обратного вызова при возникновении ошибки.
then
метод возвращает новыйPromise
Пример (заметьте, не оригинальныйPromise
пример). Поэтому можно использовать метод цепной записи, т.then
После вызова метода другогоthen
метод.
Если объединить приведенный выше пример более подробно, код будет таким.
var promise = Promise.resolve(config);
// promise.then('请求成功拦截2', '请求失败拦截2')
promise.then(function requestSuccess2(config) {
console.log('------request------success------2');
return config;
}, function requestError2(error) {
console.log('------response------error------2');
return Promise.reject(error);
})
// .then('请求成功拦截1', '请求失败拦截1')
.then(function requestSuccess1(config) {
console.log('------request------success------1');
return config;
}, function requestError1(error) {
console.log('------response------error------1');
return Promise.reject(error);
})
// .then(dispatchRequest, undefined)
.then( function dispatchRequest(config) {
/**
* 适配器返回的也是Promise 实例
adapter = function xhrAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve, reject) {})
}
**/
return adapter(config).then(function onAdapterResolution(response) {
// 省略代码 ...
return response;
}, function onAdapterRejection(reason) {
// 省略代码 ...
return Promise.reject(reason);
});
}, undefined)
// .then('响应成功拦截1', '响应失败拦截1')
.then(function responseSuccess1(response) {
console.log('------response------success------1');
return response;
}, function responseError1(error) {
console.log('------response------error------1');
return Promise.reject(error);
})
// .then('响应成功拦截2', '响应失败拦截2')
.then(function responseSuccess2(response) {
console.log('------response------success------2');
return response;
}, function responseError2(error) {
console.log('------response------error------2');
return Promise.reject(error);
})
// .then('用户写的业务处理函数')
// .catch('用户写的报错业务处理函数');
.then(function (response) {
console.log('哈哈哈,终于获取到数据了', response);
})
.catch(function (err) {
console.log('哎呀,怎么报错了', err);
});
Посмотрите внимательно на этоPromise
Цепные вызовы, код аналогичный.then
Последний параметр, возвращаемый методом, является следующимthen
Первый параметр метода.
catch
Ошибка поймать, оба возвращаютсяPromise.reject(error)
, это для удобства пользователяcatch
ошибку можно поймать.
Например:
var p1 = new Promise((resolve, reject) => {
reject(new Error({name: '若川'}));
});
p1.catch(err => {
console.log(res, 'err');
return Promise.reject(err)
})
.catch(err => {
console.log(err, 'err1');
})
.catch(err => {
console.log(err, 'err2');
});
err2
Он не будет захвачен, то есть не будет выполнен, но если оба будут возвращеныreturn Promise.reject(err)
, его можно захватить.
Наконец, нарисуйте картинку, чтобы подвести итогPromise
цепные вызовы.
Резюме: 1. Перехватчики запросов и ответов могут быть написаны
Promise
.
2. Если задано несколько ответчиков на запросы, те, которые установлены позже, будут выполняться первыми.
3. Если установлены перехватчики с несколькими ответами, сначала выполняются те, которые установлены первыми.
dispatchRequest(config)
здесьconfig
Он возвращается перехватчиком успеха запроса. см. далееdispatchRequest
функция.
5.3. Окончательный запрос на отправку по запросу dispatchRequest.
Эта функция в основном выполняет следующие действия:
1. Если отменяется, то
throw
привести к ошибкеPromise
кrejected
.
2. Убедитесь, чтоconfig.header
существует.
3. Преобразование данных с помощью пользовательских преобразователей и преобразователей запросов по умолчанию.
4. Сгладитьconfig.header
.
5. Удалите некоторыеconfig.header
.
6. Возвратный адаптерadapter
(Promise
экземпляр) после выполненияthen
после казниPromise
пример. Возвращенный результат передается перехватчику ответов для обработки.
'use strict';
// utils 工具函数
var utils = require('./../utils');
// 转换数据
var transformData = require('./transformData');
// 取消状态
var isCancel = require('../cancel/isCancel');
// 默认参数
var defaults = require('../defaults');
/**
* 抛出 错误原因,使`Promise`走向`rejected`
*/
function throwIfCancellationRequested(config) {
if (config.cancelToken) {
config.cancelToken.throwIfRequested();
}
}
/**
* Dispatch a request to the server using the configured adapter.
*
* @param {object} config The config that is to be used for the request
* @returns {Promise} The Promise to be fulfilled
*/
module.exports = function dispatchRequest(config) {
// 取消相关
throwIfCancellationRequested(config);
// Ensure headers exist
// 确保 headers 存在
config.headers = config.headers || {};
// Transform request data
// 转换请求的数据
config.data = transformData(
config.data,
config.headers,
config.transformRequest
);
// Flatten headers
// 拍平 headers
config.headers = utils.merge(
config.headers.common || {},
config.headers[config.method] || {},
config.headers || {}
);
// 以下这些方法 删除 headers
utils.forEach(
['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
function cleanHeaderConfig(method) {
delete config.headers[method];
}
);
// adapter 适配器部分 拆开 放在下文讲
};
5.3.1. Преобразовать данные преобразования данных диспетчерского запроса.
В приведенном выше коде есть функцияtransformData
, объяснил здесь. На самом деле, это обход переданного массива функций, работа с данными и, наконец, возврат данных.
axios.defaults.transformResponse
По умолчанию в массиве есть функция, поэтому используйтеconcat
Связать пользовательские функции.
использовать:
Путь к файлуaxios/examples/transform-response/index.html
Этот код на самом деле предназначен для преобразования строки в формате времени в объект времени, который можно вызвать напрямую.getMonth
и другие методы.
var ISO_8601 = /(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})Z/;
function formatDate(d) {
return (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear();
}
axios.get('https://api.github.com/users/mzabriskie', {
transformResponse: axios.defaults.transformResponse.concat(function (data, headers) {
Object.keys(data).forEach(function (k) {
if (ISO_8601.test(data[k])) {
data[k] = new Date(Date.parse(data[k]));
}
});
return data;
})
})
.then(function (res) {
document.getElementById('created').innerHTML = formatDate(res.data.created_at);
});
Исходный код:
Это обход массива и вызов передачи в массивеdata
а такжеheaders
аргументы для вызова функции.
module.exports = function transformData(data, headers, fns) {
/*eslint no-param-reassign:0*/
utils.forEach(fns, function transform(fn) {
data = fn(data, headers);
});
return data;
};
5.3.2 Исполнительная часть адаптера адаптера dispatchRequest
Адаптеры называются шаблонами адаптеров в шаблонах проектирования. Расскажите простой пример из жизни, всем легко понять.
Раньше мы использовали разъемы для наушников для мобильных телефонов, которые были круглыми отверстиями, но теперь в основном разъем для наушников и порт для зарядки объединены в один. единый какtypec
.
Тогда нам нуженtypec转圆孔的转接口
, это адаптер.
// adapter 适配器部分
var adapter = config.adapter || defaults.adapter;
return adapter(config).then(function onAdapterResolution(response) {
throwIfCancellationRequested(config);
// Transform response data
// 转换响应的数据
response.data = transformData(
response.data,
response.headers,
config.transformResponse
);
return response;
}, function onAdapterRejection(reason) {
if (!isCancel(reason)) {
// 取消相关
throwIfCancellationRequested(config);
// Transform response data
// 转换响应的数据
if (reason && reason.response) {
reason.response.data = transformData(
reason.response.data,
reason.response.headers,
config.transformResponse
);
}
}
return Promise.reject(reason);
});
Далее смотрите конкретноadapter
.
5.4 адаптер Адаптер действительно отправляет запрос
var adapter = config.adapter || defaults.adapter;
прочитайте вышеadapter
, вы можете знать, что поддерживается настройка пользователя. Например, через апплет WeChatwx.request
Также напишитеadapter
.
Тогда взглянитеdefaults.ddapter
.
Путь к файлу:axios/lib/defaults.js
Вводится в соответствии с текущей средой, если она вводится в среде браузера.xhr
,Даnode
вводится средаhttp
.
Аналогичное суждениеnode
среда, а такжеsentry-javascript
См. исходный код.
function getDefaultAdapter() {
var adapter;
// 根据 XMLHttpRequest 判断
if (typeof XMLHttpRequest !== 'undefined') {
// For browsers use XHR adapter
adapter = require('./adapters/xhr');
// 根据 process 判断
} else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
// For node use HTTP adapter
adapter = require('./adapters/http');
}
return adapter;
}
var defaults = {
adapter: getDefaultAdapter(),
// ...
};
xhr
Дальше то, что нам знакомоXMLHttpRequest
объект.
Может быть, читатели не понимают, вы можете обратиться кXMLHttpRequest Документация MDN.
Главное напоминание:onabort
запрос на отмену мероприятия,withCredentials
это логическое значение, используемое для указания междоменногоAccess-Control
Должен ли запрос содержать информацию об авторизации, такую какcookie
или уполномоченныйheader
голова.
Этот код был удален, вы можете посмотреть подробностиВакагавыaxios-analysis
склад, так же можно клонировать автораaxios-analysis
Детальный анализ будет сделан, когда склад будет отлажен.
module.exports = function xhrAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve, reject) {
// 这块代码有删减
var request = new XMLHttpRequest();
request.open()
request.timeout = config.timeout;
// 监听 state 改变
request.onreadystatechange = function handleLoad() {
if (!request || request.readyState !== 4) {
return;
}
// ...
}
// 取消
request.onabort = function(){};
// 错误
request.onerror = function(){};
// 超时
request.ontimeout = function(){};
// cookies 跨域携带 cookies 面试官常喜欢考这个
// 一个布尔值,用来指定跨域 Access-Control 请求是否应带有授权信息,如 cookie 或授权 header 头。
// Add withCredentials to request if needed
if (!utils.isUndefined(config.withCredentials)) {
request.withCredentials = !!config.withCredentials;
}
// 上传下载进度相关
// Handle progress if needed
if (typeof config.onDownloadProgress === 'function') {
request.addEventListener('progress', config.onDownloadProgress);
}
// Not all browsers support upload events
if (typeof config.onUploadProgress === 'function' && request.upload) {
request.upload.addEventListener('progress', config.onUploadProgress);
}
// Send the request
// 发送请求
request.send(requestData);
});
}
А на самом деле сейчасfetch
Поддержка очень хорошая, Али с открытым исходным кодомumi-requestЗапросите библиотеку, просто используйтеfetch
инкапсулированный, вместо использованияXMLHttpRequest
.
В конце статьи примерноumi-request
а такжеaxios
разница.
http
http
Здесь он не будет подробно описываться, и заинтересованные читатели могут ознакомиться с ним самостоятельно.Вакагавыaxios-analysis
склад.
module.exports = function httpAdapter(config) {
return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
});
};
надdispatchRequest
Есть модуль отмены, который я считаю ключевым моментом, поэтому подробно расскажу о нем в конце:
5.5 Модуль отмены dispatchRequest
можно использоватьcancel token
Отмените запрос.
axios API отмены токена основан на отзывеpromise
Отменить предложение.
The axios cancel token API is based on the withdrawn cancelable promises proposal.
Оба варианта использования подробно описаны в документации.
К сожалению, вexample
Папки также не имеют примера отмены. Автор находится вexample
в серединеexample/get
Добавлен отмененный пример на основе .axios/examples/cancel
, который читателям удобно отлаживать.
node ./examples/server.js -p 5000
request
Перехватчики в иdispatch
Отмена этих двух модулей относительно сложна, и ее можно отладить и переварить.
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/get/server', {
cancelToken: source.token
}).catch(function (err) {
if (axios.isCancel(err)) {
console.log('Request canceled', err.message);
} else {
// handle error
}
});
// cancel the request (the message parameter is optional)
// 取消函数。
source.cancel('哎呀,我被若川取消了');
5.5.1 Пример кода модуля запроса на отмену
В сочетании с процессом отмены исходного кода, вероятно, это так. Вставьте этот код вaxios/examples/cancel-token/index.html
.
параметрическийconfig.cancelToken
срабатываетsource.cancel('哎呀,我被若川取消了');
только что сгенерированный.
// source.cancel('哎呀,我被若川取消了');
// 点击取消时才会 生成 cancelToken 实例对象。
// 点击取消后,会生成原因,看懂了这段在看之后的源码,可能就好理解了。
var config = {
name: '若川',
// 这里简化了
cancelToken: {
promise: new Promise(function(resolve){
resolve({ message: '哎呀,我被若川取消了'})
}),
reason: { message: '哎呀,我被若川取消了' }
},
};
// 取消 抛出异常方法
function throwIfCancellationRequested(config){
// 取消的情况下执行这句
if(config.cancelToken){
// 这里源代码 便于执行,我改成具体代码
// config.cancelToken.throwIfRequested();
// if (this.reason) {
// throw this.reason;
// }
if(config.cancelToken.reason){
throw config.cancelToken.reason;
}
}
}
function dispatchRequest(config){
// 有可能是执行到这里就取消了,所以抛出错误会被err2 捕获到
throwIfCancellationRequested(config);
// adapter xhr适配器
return new Promise((resovle, reject) => {
var request = new XMLHttpRequest();
console.log('request', request);
if (config.cancelToken) {
// Handle cancellation
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
request.abort();
reject(cancel);
// Clean up request
request = null;
});
}
})
.then(function(res){
// 有可能是执行到这里就才取消 取消的情况下执行这句
throwIfCancellationRequested(config);
console.log('res', res);
return res;
})
.catch(function(reason){
// 有可能是执行到这里就才取消 取消的情况下执行这句
throwIfCancellationRequested(config);
console.log('reason', reason);
return Promise.reject(reason);
});
}
var promise = Promise.resolve(config);
// 没设置拦截器的情况下是这样的
promise
.then(dispatchRequest, undefined)
// 用户定义的then 和 catch
.then(function(res){
console.log('res1', res);
return res;
})
.catch(function(err){
console.log('err2', err);
return Promise.reject(err);
});
// err2 {message: "哎呀,我被若川取消了"}
5.5.2 Далее смотрим исходный код модуля отмены
посмотреть, как сгенерироватьconfig.cancelToken
.
Путь к файлу:
axios/lib/cancel/CancelToken.js
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
source.cancel('哎呀,我被若川取消了');
посмотреть на примереCancelToken.source
реализация,
CancelToken.source = function source() {
var cancel;
var token = new CancelToken(function executor(c) {
cancel = c;
});
// token
return {
token: token,
cancel: cancel
};
};
после казниsource
Примерная структура такая.
{
token: {
promise: new Promise(function(resolve){
resolve({ message: '哎呀,我被若川取消了'})
}),
reason: { message: '哎呀,我被若川取消了' }
},
cancel: function cancel(message) {
if (token.reason) {
// Cancellation has already been requested
// 已经取消
return;
}
token.reason = {message: '哎呀,我被若川取消了'};
}
}
см. далееnew CancelToken
// CancelToken
// 通过 CancelToken 来取消请求操作
function CancelToken(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function.');
}
var resolvePromise;
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
var token = this;
executor(function cancel(message) {
if (token.reason) {
// Cancellation has already been requested
// 已经取消
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
});
}
module.exports = CancelToken;
Это то, что используется в адаптере, который отправляет запрос.
// xhr
if (config.cancelToken) {
// Handle cancellation
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
request.abort();
reject(cancel);
// Clean up request
request = null;
});
}
dispatchRequest
серединаthrowIfCancellationRequested
Конкретная реализация: throw выдает исключение.
// 抛出异常函数
function throwIfCancellationRequested(config) {
if (config.cancelToken) {
config.cancelToken.throwIfRequested();
}
}
// 抛出异常 用户 { message: '哎呀,我被若川取消了' }
CancelToken.prototype.throwIfRequested = function throwIfRequested() {
if (this.reason) {
throw this.reason;
}
};
отменить стек вызовов процесса
1.source.cancel()
2.resolvePromise(token.reason);
3.config.cancelToken.promise.then(function onCanceled(cancel) {})
последняя записьrequest.abort();``reject(cancel);
Здесь представлен процесс отмены. В основном путем передачи параметров конфигурацииcancelToken
, будет генерироваться только при отменеcancelToken
, судя есть, кинь ошибку, чтобPromise
кrejected
, позвольте пользователю захватить сообщение {сообщение: 'информация об отмене, установленная пользователем'}.
Статья в основном написана здесь до конца.
Если ты дочитал до конца, значит, ты превзошел многих ^_^
axios
Это очень хорошая библиотека запросов, но она определенно не может удовлетворить потребности всех разработчиков.Далее сравните другие библиотеки, чтобы увидеть, какие конкретные потребности есть у других разработчиков.
6. Сравните с другими библиотеками запросов
6.1 KoAjax
Лидер сообщества FCC Chengdu Shuige с открытым исходным кодомKoAJAX.
Как использовать ПО с открытым исходным кодом для проведения технической конференции?Выдержка из статьи ниже.
Библиотека внешних запросов — KoAJAX Наиболее часто используемой библиотекой HTTP-запросов для домашних студентов, изучающих интерфейс, должна быть axios, верно? Хотя его Interceptor API называется .use(), он полностью отличается от промежуточного режима Node.js Express, Koa и др. По сравнению с jQuery.ajaxPrefilter() и dataFilter() существенных улучшений нет; прогресс загрузки проще, чем jQuery.Deferred(), всего две специальные опции обратного вызова. Поэтому ему все равно приходится запоминать конкретные API для конкретных требований, что недостаточно лаконично.
К счастью, Water Song работает над тем, какРеализация движка промежуточного программного обеспечения, подобного Koa, с асинхронными итераторами ES 2018В процессе было создано более практичное приложение верхнего уровня — KoAJAX. Весь его процесс выполнения основан на промежуточном программном обеспечении в стиле Koa, и сам он является стеком вызовов промежуточного программного обеспечения. В дополнение к сокращенным методам, таким как .get(), .post(), .put() и .delete(), обычно используемым в RESTful API, разработчикам нужно помнить только .use() и next(), остальные являются стандартами ES Syntax и выводом типа TS.
6.2 umi-request Библиотека запросов Alibaba с открытым исходным кодом
репозиторий umi-request на github
umi-request
а такжеfetch
, axios
Сходства и различия.
должен сказать,umi-request
Он действительно мощный, и заинтересованные читатели могут прочитать его исходный код.
пониматьaxios
на основе пониманияumi-request
Исходный код не должен быть сложным.
Напримерumi-request
Разблокировка кода модуля практически аналогичнаaxios
Точно так же.
7. Резюме
Подробности статьиaxios
Метод отладки. подробныйaxios
Реализация таких функций, как конструкторы, перехватчики, отмены и т. д. Наконец, сравниваются другие библиотеки запросов.
Наконец, нарисуйте картинку, чтобы обобщить общий процесс аксиом.
Ответьте на вопросы, заданные в начале статьи:
Если вы ищете работу, проект написан и используетсяaxios
, интервьюер может спросить вас:
1. Почему
axios
Его можно использовать как в качестве вызова функции, так и в качестве объекта, напримерaxios({})
,axios.get
.
отвечать:axios
Суть - это функция, и назначаются некоторые методы-псевдонимы, такие какget
,post
Метод может быть вызван, и окончательный вызов по-прежнемуAxios.prototype.request
функция.
2. Краткое описание
axios
процесс вызова.
Ответ: на самом деле называетсяAxios.prototype.request
метод, окончательный результатpromise
Сцепленные вызовы, фактический запрос находится вdispatchRequest
распространяется в.
3. Вы когда-нибудь использовали перехватчик? Каков принцип?
Ответ: б/у, б/уaxios.interceptors.request.use
Добавьте функции перехватчика успешных и неудачных запросов сaxios.interceptors.response.use
Добавьте функции перехватчика успешного и неудачного ответа. существуетAxios.prototype.request
функциональная композицияpromise
При объединении вызововInterceptors.protype.forEach
Добавлены перехватчики запроса и ответа для фактической отправки запроса.dispatchRequest
Оба конца запроса, чтобы обеспечить перехват до запроса и перехват после ответа. Перехватчики также поддерживают использованиеInterceptors.protype.eject
метод удален.
4. Используйте
axios
функция отмены? Как это достигается?
A: Используется, проходя мимоconfig
настроитьcancelToken
форму для отмены. СуждениеcancelToken
,существуетpromise
прикованныйdispatchRequest
выдает ошибку наadapter
серединаrequest.abort()
отменить запросpromise
кrejected
, информация об отмене фиксируется пользователем.
5. Почему он поддерживает отправку запросов в браузерах?
node
послать запрос?
отвечать:axios.defaults.adapter
В конфигурации по умолчанию браузер или среда оцениваются в соответствии со средой.node
среде используйте соответствующий адаптер. Адаптер поддерживает настройку.
Чтобы ответить на вопросы интервьюера, читатели также могут организовать язык в соответствии со своим пониманием Ответ автора только для справки.
axios
Исходный код относительно небольшой, более тысячи строк после упаковки, его относительно легко читать, и его очень стоит изучить.
предложениеclone
GitHub-репозиторий аксиального анализа Вакагавы, отлаживайте сами по методике в тексте, а мне больше импонирует.
на основеPromise
, составляютPromise
Цепочка, ловко настройте перехват запроса, отправьте запрос и снова попробуйте перехватчик ответа.
request
Перехватчики в иdispatch
Отмена этих двух модулей относительно сложна, и ее можно отладить и переварить.
axios
Это функция, когда это функция, вызовAxios.prototype.request
функция, которая также является объектом, на которомget
,post
Дождитесь метода запроса и, наконец, вызовитеAxios.prototype.request
функция.
axios
В исходном коде используется множество шаблонов проектирования. Например, заводской режим, режим итератора, режим адаптера и т. д. Если вы хотите систематически изучать шаблоны проектирования, обычно рекомендуется иметь показатель Доубана 9,1.Шаблоны проектирования JavaScript и практика разработки
Если читатель обнаружит что-то неправильное или что-то, что можно улучшить, или где это неясно написано, пожалуйста, прокомментируйте и укажите. Кроме того, я чувствую, что написание хорошее, и это немного полезно для вас.Вы можете ставить лайки, комментировать, пересылать и делиться, что также является своего рода поддержкой для автора.Большое спасибо.
Рекомендуемое чтение
Официальный репозиторий axios на github
Прежде чем написать статью, я искал и читал следующие статьи. Заинтересованы в сравнении следующих статей, основанных на отладке кода, это выглядит быстро.
Я всегда чувствую, что поиск еще нескольких статей полезнее для получения знаний. Есть такое понятие, как тематическое чтение. Это, вероятно, означает серию чтений по теме.
@Позвони мне Сяомин: анализ исходного кода Axios
@NikuNikusan: объясните исходный код axios простым языком
@小thief Mr. _ronffy: Углубленный анализ исходного кода Axios — новый король AJAX
Построчный разбор исходного кода Axios
Как Axios инкапсулирует HTTP-запросы
Знакомство с @Lee: рефакторинг TypeScript Обмен опытом Axios
Очередная серия автора
Интервьюер спросил: наследование JS
Интервьюер спросил: этот пункт JS
Интервьюер спросил: Могу ли я смоделировать вызов и применить методы JS?
Интервьюер спросил: Могу ли я смоделировать метод привязки, реализующий JS?
Интервьюер спросил: Могу ли я смоделировать новый оператор, реализующий JS?
о
Автор: Чанг ИВакагаваНазвание смешано в реках и озерах. По дороге на фронт | Энтузиасты РРТ | Знаю очень мало, только хорошо учусь.
Блог Вакагавы,использоватьvuepress
Рефакторинг, опыт чтения может быть лучше
Колонка самородков, добро пожаловать, обратите внимание~
segmentfault
Передняя колонка обзора, добро пожаловать, обратите внимание~
Знайте переднюю колонку видения, добро пожаловать, обратите внимание~
github blog, соответствующий исходный код и ресурсы размещены здесь, попросите одинstar
^_^~
Добро пожаловать, чтобы добавить общедоступную учетную запись WeChat для общения в WeChat
Может быть более интересным общедоступный аккаунт WeChat, нажмите и удерживайте, чтобы отсканировать код, чтобы следовать. Добро пожаловать, чтобы добавить автора WeChatruochuan12
(Укажите источник, в основном никто не будет отклонен), пригласите вас в [Группу обмена видением переднего плана] для долгосрочного обмена и обучения ~