1. Введение
Привет всем, яВакагава. Добро пожаловать, чтобы следовать за мнойПубличный аккаунт Wakagawa Vision, недавно организованныйЧтение исходного кода, если вам интересно, вы можете добавить меня в WeChatruochuan12Участвуйте в долгосрочном обмене и обучении.
написано раньше"Изучение серии "Общая архитектура исходного кода""ВключатьjQuery
,underscore
,lodash
,vuex
,sentry
,axios
,redux
,koa
,vue-devtools
,vuex4
Более десяти статей с исходным кодом. Два последних из них:
Выпущен Vue 3.2, как Ю Юйси выпустил Vue.js?
Практические основные функции инструментов в исходном коде Vue3, понятные новичкам.
Написание относительно сложного исходного кода стоило мне времени и энергии, и я не получил много лайков от чтения.На самом деле, это был настоящий удар. С точки зрения объема чтения и выгоды для читателей это не может способствовать непрерывному выпуску статей авторами.
Так что измените свое мнение и напишите несколько относительно простых для понимания статей.На самом деле исходный код не так сложен, как можно себе представить, по крайней мере многие люди могут понять.
Я уже писал статьи с исходным кодом koa.Изучите общую архитектуру исходного кода koa, проанализируйте принцип луковой модели koa и принцип совместной работы.Она относительно длинная, и читатели и друзья, скорее всего, не смогут ее закончить, поэтому эта статья начинается сkoa-compose
50 строк исходного кода.
эта статья посвященарепозиторий koa-composeфайл, весьindex.js
Хотя количество строк кода в файле меньше50
ОК, и тестовый примерtest/test.js
документ300
Это больше, чем линия, но этому стоит научиться.
Гёте однажды сказал: «Читать хорошую книгу — значит разговаривать с благородными людьми». То же самое можно получить: чтение исходного кода — это тоже способ обучения и общения с автором.
Прочитав эту статью, вы узнаете:
1. 熟悉 koa-compose 中间件源码、可以应对面试官相关问题
2. 学会使用测试用例调试源码
3. 学会 jest 部分用法
2. Подготовка окружающей среды
2.1 Клонировать проект koa-compose
Адрес склада этой статьи: koa-compose-analysis, спроситьstar
~
# 可以直接克隆我的仓库,我的仓库保留的 compose 仓库的 git 记录
git clone https://github.com/lxchuan12/koa-compose-analysis.git
cd koa-compose/compose
npm i
Кстати: как мне сохранитьcompose
складgit
записано.
# 在 github 上新建一个仓库 `koa-compose-analysis` 克隆下来
git clone https://github.com/lxchuan12/koa-compose-analysis.git
cd koa-compose-analysis
git subtree add --prefix=compose https://github.com/koajs/compose.git main
# 这样就把 compose 文件夹克隆到自己的 git 仓库了。且保留的 git 记录
о большемgit subtree
, вы можете увидеть эту статьюДвунаправленная синхронизация подпроектов между несколькими проектами Git с помощью Git Subtree с кратким руководством
Далее давайте посмотрим, как отлаживать исходный код в соответствии с тестовыми примерами, представленными в проекте с открытым исходным кодом.
2.2 Отладка исходного кода компоновки в соответствии с тестовым набором
использоватьVSCode
(моя версия1.60
), чтобы открыть проект и найтиcompose/package.json
,оказатьсяscripts
а такжеtest
Заказ.
// compose/package.json
{
"name": "koa-compose",
// debug (调试)
"scripts": {
"eslint": "standard --fix .",
"test": "jest"
},
}
существуетscripts
Там должен бытьdebug
или调试
шрифт. нажмитеdebug
(отладка), выберитеtest
.
Затем будет выполнен тестовый примерtest/test.js
документ. Вывод терминала показан на изображении ниже.
Затем мы отлаживаемcompose/test/test.js
документ.
мы можем45行
Нажмите точку останова и нажмите еще разpackage.json
=> srcipts
=> test
Войдите в режим отладки.
Как показано ниже.
Затем нажмите кнопку выше, чтобы продолжить отладку. существуетcompose/index.js
Ставьте точки останова в ключевых местах файла, а отлаживайте и изучайте исходный код с вдвое меньшими усилиями.
Кстати, несколько кнопок, связанных с отладкой, подробно описаны.
-
- Продолжить (F5): После нажатия код будет выполнен непосредственно до следующей точки останова, если следующей точки останова нет, считается, что выполнение текущего кода завершено.
-
- Пропуск одного шага (F10): после нажатия выполняется переход к следующей строке текущего кода для продолжения выполнения, и функция не запускается.
-
- Пошаговая отладка (F11): нажмите, чтобы войти во внутреннюю отладку текущей функции, например, в
compose
Выполните пошаговую отладку в этой строке, и вы войдете вcompose
Отладка внутри функции.
- Пошаговая отладка (F11): нажмите, чтобы войти во внутреннюю отладку текущей функции, например, в
-
- Выход (Shift + F11): нажмите, чтобы выйти из текущей отлаживаемой функции, что соответствует одноэтапной отладке.
-
- Перезагрузите (Ctrl + Shift + F5): как следует из названия.
-
- Разорвать ссылку (Shift + F5): как следует из названия.
Далее мы следуем тестовому примеру, чтобы изучить исходный код.
3. Следуйте тестовому примеру, чтобы изучить исходный код
Поделитесь советом по тест-кейсу: мы можем добавить тест-кейсonly
ретушь.
// 例如
it.only('should work', async () => {})
Таким образом, мы можем просто выполнить текущий тестовый пример и не заботиться о других, не мешая отладке.
3.1 Нормальный процесс
Открытьcompose/test/test.js
файл, см. первый тестовый пример.
// compose/test/test.js
'use strict'
/* eslint-env jest */
const compose = require('..')
const assert = require('assert')
function wait (ms) {
return new Promise((resolve) => setTimeout(resolve, ms || 1))
}
// 分组
describe('Koa Compose', function () {
it.only('should work', async () => {
const arr = []
const stack = []
stack.push(async (context, next) => {
arr.push(1)
await wait(1)
await next()
await wait(1)
arr.push(6)
})
stack.push(async (context, next) => {
arr.push(2)
await wait(1)
await next()
await wait(1)
arr.push(5)
})
stack.push(async (context, next) => {
arr.push(3)
await wait(1)
await next()
await wait(1)
arr.push(4)
})
await compose(stack)({})
// 最后输出数组是 [1,2,3,4,5,6]
expect(arr).toEqual(expect.arrayContaining([1, 2, 3, 4, 5, 6]))
})
}
Прочитав этот тестовый пример,context
что это такое,next
Что это такое.
существуетkoa
документацияСуществует очень репрезентативное промежуточное ПО наgif
картина.
а такжеcompose
Функция функции состоит в том, чтобы добавить функцию, добавленную в массив промежуточного программного обеспечения в соответствии с приведенным вышеgif
Последовательное выполнение графов.
3.1.1 функция создания
Проще говоря,compose
Функция в основном делает две вещи.
-
- Принимает один параметр, параметр проверки — это массив, а каждый элемент в массиве проверки — это функция.
-
- Возвращает функцию, которая принимает два параметра, а именно
context
а такжеnext
, эта функция, наконец, возвращаетPromise
.
- Возвращает функцию, которая принимает два параметра, а именно
/**
* Compose `middleware` returning
* a fully valid middleware comprised
* of all those which are passed.
*
* @param {Array} middleware
* @return {Function}
* @api public
*/
function compose (middleware) {
// 校验传入的参数是数组,校验数组中每一项是函数
if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')
for (const fn of middleware) {
if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
}
/**
* @param {Object} context
* @return {Promise}
* @api public
*/
return function (context, next) {
// last called middleware #
let index = -1
return dispatch(0)
function dispatch(i){
// 省略,下文讲述
}
}
}
Давайте посмотримdispatch
функция.
3.1.2 диспетчерская функция
function dispatch (i) {
// 一个函数中多次调用报错
// await next()
// await next()
if (i <= index) return Promise.reject(new Error('next() called multiple times'))
index = i
// 取出数组里的 fn1, fn2, fn3...
let fn = middleware[i]
// 最后 相等,next 为 undefined
if (i === middleware.length) fn = next
// 直接返回 Promise.resolve()
if (!fn) return Promise.resolve()
try {
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)))
} catch (err) {
return Promise.reject(err)
}
}
Стоит отметить, что:bind
Функция — это функция, которая возвращает новый. Первый параметр — это указатель this в функции (если функции не нужно использоватьthis
, обычно записывается какnull
).
это предложениеfn(context, dispatch.bind(null, i + 1)
,i + 1
это дляlet fn = middleware[i]
Выбиратьmiddleware
следующая функция в .
то естьnext
это функция в следующем промежуточном программном обеспечении. также объясните вышеgif
Порядок выполнения функции графа.
Окончательный порядок массива в тестовом примере:[1,2,3,4,5,6]
.
3.1.3 Упрощение создания для облегчения понимания
После самостоятельной отладки вы обнаружитеcompose
После выполнения это структура, подобная этой (опуститьtry catch
судить).
// 这样就可能更好理解了。
// simpleKoaCompose
const [fn1, fn2, fn3] = stack;
const fnMiddleware = function(context){
return Promise.resolve(
fn1(context, function next(){
return Promise.resolve(
fn2(context, function next(){
return Promise.resolve(
fn3(context, function next(){
return Promise.resolve();
})
)
})
)
})
);
};
то есть
koa-compose
возвращаетPromise
,от中间件(传入的数组)
Вынесите первую функцию изcontext
и первыйnext
функция для выполнения.
Первыйnext
Функция также возвращаетPromise
,от中间件(传入的数组)
Уберите вторую функцию изcontext
и второйnext
функция для выполнения.
второйnext
Функция также возвращаетPromise
,от中间件(传入的数组)
Вычеркните третью функцию изcontext
и третийnext
функция для выполнения.
Третий...
И так далее. В последнем мидлваре есть вызовnext
функция, она возвращаетPromise.resolve
. Если нет, не выполнятьnext
функция.
Это соединяет все промежуточное ПО последовательно. Это то, что мы часто называем моделью лука.
Я должен сказать, что это очень удивительно, «играть все равно великий бог будет играть».
3.2 Перехват ошибок
it('should catch downstream errors', async () => {
const arr = []
const stack = []
stack.push(async (ctx, next) => {
arr.push(1)
try {
arr.push(6)
await next()
arr.push(7)
} catch (err) {
arr.push(2)
}
arr.push(3)
})
stack.push(async (ctx, next) => {
arr.push(4)
throw new Error()
})
await compose(stack)({})
// 输出顺序 是 [ 1, 6, 4, 2, 3 ]
expect(arr).toEqual([1, 6, 4, 2, 3])
})
Поверьте, чтобы понять первый тестовый пример иcompose
функция, также лучше понять этот тестовый пример. Эта часть на самом деле является соответствующим кодом здесь.
try {
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)))
} catch (err) {
return Promise.reject(err)
}
3.3 Следующая функция не может быть вызвана несколько раз
it('should throw if next() is called multiple times', () => {
return compose([
async (ctx, next) => {
await next()
await next()
}
])({}).then(() => {
throw new Error('boom')
}, (err) => {
assert(/multiple times/.test(err.message))
})
})
Этому соответствует:
index = -1
dispatch(0)
function dispatch (i) {
if (i <= index) return Promise.reject(new Error('next() called multiple times'))
index = i
}
после двойного звонкаi
а такжеindex
как для1
, поэтому будет сообщено об ошибке.
compose/test/test.js
В файле более 300 строк, и есть много тестовых случаев, которые можно отлаживать самостоятельно по методам, описанным в тексте.
4. Резюме
несмотря на то чтоkoa-compose
Исходный код составляет менее 50 строк, но если вы впервые видите исходный код для отладки исходного кода, это все равно будет сложно. Он смешивается с функциями высшего порядка, замыканиями,Promise
,bind
и другие базовые знания.
Благодаря этой статье мы познакомились сkoa-compose
Луковая модель, о которой часто говорит промежуточное ПО, я изучил ее частьjest
использования, а также научились использовать готовые тест-кейсы для отладки исходного кода.
Я считаю, что после того, как вы научитесь отлаживать исходный код с помощью тестовых примеров, вы почувствуете, что исходный код не так сложен, как вы думаете..
Проекты с открытым исходным кодом обычно имеют очень подробные тестовые примеры. Помимо удобства в изучении исходного кода и отладки исходного кода, это также может вдохновить нас: мы также можем постепенно внедрять инструменты тестирования для проектов в нашу собственную работу, такие какjest
.
Кроме того, чтение исходного кода проектов с открытым исходным кодом является для нас лучшим способом изучить дизайнерские идеи и реализацию исходного кода крупных коров отрасли.
Прочитав эту статью, я очень надеюсь, что смогу попрактиковаться в отладке исходного кода, чтобы научиться самому, который легко усваивается и переваривается. Кроме того, если у вас есть лишняя энергия, вы можете продолжать смотреть мойkoa-compose
Исходная статья:Изучите общую архитектуру исходного кода koa, проанализируйте принцип луковой модели koa и принцип совместной работы.
Наконец, добро пожаловать, чтобы добавить меня на WeChatruochuan12общаться, участвоватьЧитайте исходный код вместеДействия, все вместе изучают исходный код и вместе добиваются прогресса.
О группе && Exchange
недавно организованныйЧтение исходного кода, если вам интересно, вы можете добавить меня в WeChatruochuan12Участвуйте в долгосрочном обмене и обучении.
Автор: Чанг ИВакагаваНазвание смешано в реках и озерах. добро пожаловать, чтобы добавить меня wechatruochuan12
. По дороге на фронт | Знаю очень мало, только хорошо учусь.
Обратите внимание на паблик аккаунта Ruochuan Vision, Изучайте исходный код вместе каждую неделю, учитесь читать исходный код и переходите к расширенному интерфейсу.
Блог Вакагавы
segmentfault
Колонна Вакагава Видение, открылВидение ВакагаваКолонка, добро пожаловать на внимание ~
Колонка самородков, добро пожаловать, обратите внимание~
Колонна видений Чжиху Руочуань, открылВидение ВакагаваКолонка, добро пожаловать на внимание ~
github blog, спроситьstar
^_^~