Особенности и преимущества koa2
что такое коа2
- Официальный API Nodejs поддерживает модель асинхронного программирования в форме обратного вызова. Проблема: проблема вложения обратного вызова
- koa2 был создан первоначальной командой Express.Сейчас это популярный фреймворк для веб-разработки на основе платформы Node.js.Koa удаляет встроенный маршрутизатор, представление и другие функции Express, делая сам фреймворк легче и масштабируемее. Сильный секс. Использование koa для написания веб-приложений позволяет избежать повторяющихся и громоздких функций обратного вызова.
Об авторе: koala, сосредоточив внимание на совместном использовании полного стека технологий Node.js, от JavaScript до Node.js, до серверной базы данных, я желаю вам стать отличным старшим инженером Node.js. [Руководство по развитию программиста] Автор, блог Github с открытым исходным кодомGitHub.com/koala-co Nth…
Преимущества коа2
Преимущество это вещь, прямо скажу насколько она хороша, вы можете не радоваться, но мы можем сравнить! Здесь я лишь говорю, какие преимущества он дает по сравнению с родным сервисом открытия http на Node.js!
- Давайте сначала взглянем на нативный Node.js Я запускаю http-сервис
const http = require('http');
http.createServer((req,res)=>{
res.writeHead(200);
res.end('hi koala');
}).listen(3000);
- Взгляните на запуск http-сервиса с помощью koa2.
const Koa = require('koa') ;
const app = new Koa();
const {createReadStream} = require('fs');
app.use(async (ctx,next)=>{
if(ctx.path === '/favicon.ico'){
ctx.body = createReadStream('./avicon.ico')
}else{
await next();
}
});
app.use(ctx=>{
ctx.body = 'hi koala';
})
app.listen(3000);
Я добавил реализацию решения /favicon.ico в koa2. С помощью приведенных выше двух фрагментов кода вы найдете следующие три преимущества.
- Традиционный http-сервис хочет использовать
模块化
Это не очень удобно, мы не можем судить обо всех запросах и каком-то контенте в одном сервисе. А koa2 лучше помогает модульности. - koa2 инкапсулирует req и res в
context
, более кратким и легко запоминающимся - Механизм промежуточного программного обеспечения, использующий
洋葱模型
, процесс модели onion запоминает одну точку (Лук сначала из кожи к сердцу, затем от сердца к коже), поместите код через модель лука流程化
,Позволять流水线
Чтобы быть более ясным, если промежуточное ПО не используется, вcreateServer
Одна строка, оценивающая всю логику, действительно плоха. - Есть также много преимуществ, которые нельзя увидеть, например, обработка ошибок, повторная инкапсуляция и т. д.
Реализовать koa2 самостоятельно
В процессе реализации посмотрю, какие знания можно усвоить
Простая инкапсуляция функции прослушивания
Когда koa2 используется напрямую, мы передаемconst app = new Koa();
,koa
Должен быть классом и может вызываться напрямуюlisten
функционировать и не подвергатьhttp
Создание сервиса, описанного вlisten
Служба может быть создана в функции. На данный момент простая реализация кода должна выглядеть так:
class Kkb{
constructor(){
this.middlewares = [];
}
listen(...args){
http.createServer(async (req,res)=>{
// 给用户返回信息
this.callback(req,res);
res.writeHead(200);
res.statusCode = 200;
res.end('hello koala')
}).listen(...args)
}
}
module.exports = Kkb;
Реализовать инкапсуляцию контекста
После реализации простого прослушивания вы обнаружите, что функция обратного вызова по-прежнему возвращает req и res.Было бы лучше, если бы они были инкапсулированы в контекст и возвращены один раз! мы продолжим
const ctx = this.createContext(req,res);
Взгляните на конкретную реализацию createContext
const request = require('./lib/request');
const response = require('./lib/response');
const context = require('./lib/context');
createContext(req,res){
// 创建一个新对象,继承导入的context
const ctx = Object.create(context);
ctx.request = Object.create(request);
ctx.response = Object.create(response);
// 这里的两等于判断,让使用者既可以直接使用ctx,也可以使用原生的内容
ctx.req = ctx.request.req = req;
ctx.res = ctx.response.res = res;
return ctx;
}
context.js
module.exports = {
get url(){
return this.request.url;
},
get body(){
return this.response.body;
},
set body(val){
this.response.body = val;
}
}
request.js
module.exports = {
get url(){
return this.req.url;
}
}
Здесь при написании context.js используются функции set и get, оператор get привязывается к свойству объекта как функция, и функция вызывается при доступе к свойству. Синтаксис set может привязать функцию к указанному свойству текущего объекта.Когда это свойство назначено, функция, которую вы привязываете, будет вызываться.
Реализовать луковую модель
Другой сценарий применения compose
Прежде чем говорить о луковой модели, давайте посмотрим на содержание функционального программирования: Студенты, которые использовали редукцию во внешнем интерфейсе функции составления, должны быть знакомы с ней. Redux обрабатывает промежуточное ПО через композицию. Принцип заключается в переборе параметров массива с помощью редукции массива.
// redux 中的 compose 函数
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
Реализация луковой модели
Посмотрите на начало статьи KOA2 создают функцию службы HTTP, вы найдете несколько вызовов в функции, на самом деле, это приложение модели лука.
Луковица состоит из многих слоев. Вы можете думать о каждом промежуточном программном обеспечении как о слое в луковице. В соответствии с последовательностью вызовов app.use промежуточное программное обеспечение формирует всю луковицу от внешнего слоя до внутреннего слоя. Выполнение всего промежуточного программного обеспечения процесс эквивалентен Проникает через всю луковицу снаружи внутрь и обратно наружу
Чтобы процитировать известную диаграмму модели лука:
Каждый раз, когда функция использования выполняется, мы фактически переходим к函数数组
В него добавляется функция, а затем функция compose снова используется для обработки порядка выполнения добавленных функций, то есть функция compose реализует механизм модели onion.
Конкретный код реализован следующим образом:
// 其中包含一个递归
compose(middlewares){
return async function(ctx){// 传入上下文
return dispatch(0);
function dispatch(i){
let fn = middlewares[i];
if(!fn){
return Promise.resolve();
}
return Promise.resolve(
fn(ctx,function next(){
return dispatch(i+1)
})
)
}
}
}
Сначала выполните диспетчеризацию (0) один раз, которая должна вернуть первую функцию, переданную app.use по умолчанию, и используйте функцию Promise для инкапсуляции возврата, где первый параметр — это наш обычно используемый ctx,
Второй параметр — это параметр next.После каждого выполнения next он будет равен следующей функции промежуточного программного обеспечения.Если следующая функция промежуточного программного обеспечения неверна, она вернет успешное обещание. Таким образом, каждый раз, когда мы вызываем next(), мы выполняем следующую промежуточную функцию.
Давайте попробуем нашу собственную реализацию koa2
Давайте использовать наш собственный koa2, и использовать его, чтобы сделать вопрос интервью о луковой модели.Я думаю, если вы понимаете статью, вывод не должен быть неправильным.Попробуйте сами!
const KKB = require('./kkb');
const app = new KKB();
app.use(async (ctx,next)=>{
ctx.body = '1';
await next();
ctx.body += '3';
})
app.use(async (ctx,next)=>{
ctx.body += '4';
await delay();
await next();
ctx.body += '5';
})
app.use(async (ctx,next)=>{
ctx.body += '6'
})
async function delay(){
return new Promise((reslove,reject)=>{
setTimeout(()=>{
reslove();
},1000);
})
}
app.listen(3000);
Идеи решения проблем: Еще лук думал,Лук сначала от кожуры к сердцевине, потом от сердцевины к кожуре
Отвечать: 1 4 6 5 3
Дополнение и пояснение
Основная цель этой статьи — дать каждому изучить базовый процесс koa2, просто реализовать koa2, а затем прочитать исходный код, чтобы иметь четкое представление. В фактическом исходном коде есть еще много отличных моментов, которые стоит изучить.Далее я перечислю еще один момент, который я считаю очень хорошим:обработка ошибок, вы можете продолжать реализовывать его на исходной основе, или вы можете прочитать исходный код, чтобы продолжить чтение! давай давай
В исходном коде koa наследуется отEmiiterЧтобы иметь дело с возможными исключениями, возникающими в любое время, подпишитесь на событие ошибки. обработка ошибок имеет два уровня: один — обработка ошибок (результат ответа на основные решения), глобальный уровень приложения (в основном отвечает за журнал), а другой — процесс ответа, коа есть уровень приложения по умолчанию для события onerror для вывода журнала ошибок.
// 在调用洋葱模型函数后面,koa 会挂载一个默认的错误处理【运行时确定异常处理】
if (!this.listenerCount("error")) this.on("error", this.onerror);
onerror(err) {
if (!(err instanceof Error))
throw new TypeError(util.format("non-error thrown: %j", err));
if (404 == err.status || err.expose) return;
if (this.silent) return;
const msg = err.stack || err.toString();
console.error();
console.error(msg.replace(/^/gm, " "));
console.error();
}
Печать об ошибке реализована через Emiger, и Emizer использует Post-подписанный шаблон дизайна. Если у вас есть небольшой партнер, который неясен с Emiger, вы можете увидеть мою статью.[Интерпретация исходного кода] В этой статье подробно рассматривается модуль Events..
Суммировать
В этой статье основное внимание уделяется идеям, код и реализация очень просты, инкапсуляция, рекурсия и шаблоны проектирования немного обсуждаются, я надеюсь, что это также может немного улучшить вас и позволить вам взглянуть на исходный код koa2. , увидимся в следующей статье.
Оригинальные статьи серии Node
Глубокое понимание процессов и нитей в Node.js
Я хочу изучать Node.js, поток, прежде чем нужно выяснить
Когда требуется, вы действительно понимаете разницу между экспортом и модулем.экспорт?
В статье об интерпретации исходного кода подробно рассматривается модуль Events.
Node.js расширенное расширенное изучение файлового модуля fs
Подписывайтесь на меня
- Добро пожаловать, чтобы добавить меня в WeChat [coder_qi], пригласить вас в техническую группу, долгосрочный обмен и изучение...
- Добро пожаловать, чтобы обратить внимание на «Руководство по развитию программиста на севере», общедоступную учетную запись, которая поможет вам расти с душой...