nodejs 미들웨어 Koa와 Express 비교
관련 추천: "nodejs Tutorial"
미들웨어라고 하면 많은 개발자들이 Koa.js를 떠올릴 것이고, Koa.js의 미들웨어 디자인은 의심할 여지 없이 프론트엔드 미들웨어 사고의 전형적인 대표자 중 하나입니다.
최근에 이 부분의 콘텐츠를 검토하면서 그 훌륭함에 대해 독자 여러분과 이야기를 나누고 싶습니다!
Koa는 사용하기 매우 편리합니다. Express에 비해 "완벽한 미들웨어" 디자인으로 인해 기능이 매우 단순해 보입니다! 저자는 프로젝트에서 이것을 사용했습니다:
const Koa=require('koa') const app=new Koa() const Router=require('koa-router') const router=new Router() const cors=require('koa2-cors') const koaBody=require('koa-body') const ENV='test-mpin2' app.use(cors({ origin:['http://localhost:9528'], // 也可以写为:['*'] credentials:true })) app.use(koaBody({ multipart:true })) app.use(async(ctx,next)=>{ console.log('访问全局中间件') ctx.state.env=ENV // 全局缓存 await next() }) const playlist=require('./controller/playlist.js') router.use('/playlist',playlist.routes()) const blog=require('./controller/blog.js') router.use('/blog',blog.routes()) app.use(router.routes()).use(router.allowedMethods()) app.listen(3000,()=>{ console.log('服务已开启') })
라우팅 라우터를 추출하여 별도의 미들웨어로 사용하며, 앱은 전역 처리만 담당합니다. 또 다른 예:
// 最外层中间件,可以用于兜底 Koa 全局错误 app.use(async (ctx, next) => { try { // 执行下一个中间件 await next(); } catch (error) { console.log(`[koa error]: ${error.message}`) } }); // 第二层中间件,可以用于日志记录 app.use(async (ctx, next) => { const { req } = ctx; console.log(`req is ${JSON.stringify(req)}`); await next(); console.log(`res is ${JSON.stringify(ctx.res)}`); });
Koa를 구현하기 쉽습니다!
위 코드와 같이 Koa 인스턴스를 살펴보고 use 메소드를 통해 미들웨어를 등록하고 연결해 보겠습니다. 소스 코드의 간단한 구현은 다음과 같이 표현할 수 있습니다.
use(fn) { this.middleware.push(fn); return this; }
미들웨어를 this.middleware
배열인데 미들웨어는 어떻게 실행되나요? 아래 소스코드를 참고하세요. this.middleware
数组中,那么中间件是如何被执行的呢?参考下面源码:
// 通过 createServer 方法启动一个 Node.js 服务 listen(...args) { const server = http.createServer(this.callback()); server.listen(...args); }
Koa 框架通过 http 模块的 createServer
方法创建一个 Node.js 服务,并传入 this.callback()
方法, callback源码简单实现如下:
callback(){ const fn=compose(this.middlewareList) return (req,res)=>{ const ctx=createContext(req,res) return this.handleRequest(ctx,fn) } } handleRequest(ctx, fn) { const onerror = err => ctx.onerror(err); // 将 ctx 对象传递给中间件函数 fn return fn(ctx).catch(onerror); }
如上代码,我们将 Koa 一个中间件组合和执行流程梳理为以下步骤:
通过一个方法(我们称为compose)组合各种中间件,返回一个中间件组合函数
fn
请求过来时,会先调用
handleRequest
方法,该方法完成:- 调用
createContext
方法,对该次请求封装出一个ctx对象; - 接着调用
this.handleRequest(ctx, fn)
处理该次请求。
- 调用
其中,核心过程就是使用compose方法组合各种中间件 —— 这是一个单独的方法,它应该不受Koa其余方法的约束。其源码简单实现为:
// 组合中间件 // 和express中的next函数意义一样 function compose(middlewareList){ // return function意思是返回一个函数 return function(ctx,next){ // 各种中间件调用的逻辑 function dispatch(i){ const fn=middlewareList[i] || next if(fn){ try{ // koa中都是async,其返回的是一个promise(对象) return Promise.resolve(fn(ctx,function next(){ return dispatch(i+1) })) }catch(err){ return Promise.reject(err) } }else{ return Promise.resolve() } } return dispatch(0) } }
其功能可以表示为这样(非源码):
async function middleware1() { //... await (async function middleware2() { //... await (async function middleware3() { //... }); //... }); //... }
到这里我们其实可以“初窥”其原理,有两点:
- Koa 的中间件机制被社区形象地总结为洋葱模型;
所谓洋葱模型,就是指每一个 Koa 中间件都是一层洋葱圈,它即可以掌管请求进入,也可以掌管响应返回。换句话说:外层的中间件可以影响内层的请求和响应阶段,内层的中间件只能影响外层的响应阶段。
- dispatch(n)对应第 n 个中间件的执行,在使用中即第 n 个中间件可以通过await next()来“插入”执行下一个中间件,同时在最后一个中间件执行完成后,依然有恢复执行的能力。即:通过洋葱模型,await next()控制调用后面的中间件,直到全局没有可执行的中间件且堆栈执行完毕,最终“原路返回”至第一个执行next的中间件。这种方式有个优点,特别是对于日志记录以及错误处理等全局功能需要非常友好。
Koa1 的中间件实现利用了 Generator 函数 + co 库(一种基于 Promise 的 Generator 函数流程管理工具),来实现协程运行。本质上,Koa v1 中间件和 Koa v2 中间件思想是类似的,只不过 Koa v2 改用了 Async/Await 来替换 Generator 函数 + co 库,整体实现更加巧妙,代码更加优雅。—— from《狼书》
经过上述部分源码的描述,我们就可以采用es6的方式将其组合起来:
// myKoa.js文件 const http=require('http') function compose(){} //见上 class LikeKoa2{ constructor() { this.middlewareList=[] } use(){} //见上 // 把所有的req,res属性、事件都交给ctx(这里只是简写) createContext(req,res){ const ctx={ req, res } // 比如 ctx.query=req,query return ctx } handleRequest(){} //见上 callback(){} //见上 listen(){} //见上 } // koa和express的不同之一: // express在调用时直接调用函数:const app=express();所以暴露出去new过的对象——具体见下面链接中代码 // 但是koa调用时以类的方式:const app=new Koa();所以直接暴露出去 module.exports=LikeKoa2
那use方法和其余方法并不相通,它是如何被执行的呢?执行了createServer后是不是相当于建立了一个通道、挂载了一个监听函数呢?
这一点恐怕就要到Node的源码中一探究竟了…
对比 Koa,聊聊 Express 原理
说起 Node.js 框架,我们一定忘不了 Express —— 不同于 Koa,它继承了路由、静态服务器和模板引擎等功能,虽然比之Koa显得“臃肿”了许多,但看上去比 Koa 更像是一个框架。通过学习 Express 源码,笔者简单的总结了它的工作机制:
通过app.use方法注册中间件。
一个中间件可以理解为一个 Layer 对象,其中包含了当前路由匹配的正则信息以及 handle 方法。
所有中间件(Layer 对象)使用stack数组存储起来。
当一个请求过来时,会从 req 中获取请求 path,根据 path 从stack中找到匹配的 Layer,具体匹配过程由
router.handle
函数实现。router.handle
函数通过next()
Koa 프레임워크는 http 모듈의((req, res) => { console.log('第一个中间件'); ((req, res) => { console.log('第二个中间件'); (async(req, res) => { console.log('第三个中间件'); await sleep(2000) res.status(200).send('hello') })(req, res) console.log('第二个中间件调用结束'); })(req, res) console.log('第一个中间件调用结束') })(req, res)
로그인 후 복사로그인 후 복사createServer
메소드를 통해 Node.js 서비스를 생성하고this.callback()</code에 전달합니다. > 메소드는 다음과 같이 간단하게 구현됩니다. 🎜rrreee🎜위 코드에서 볼 수 있듯이 Koa 미들웨어 조합 및 실행 프로세스를 다음 단계로 구성합니다. 🎜<ul style="list-style-type: disc;"><li>🎜컴포즈(compose)라는 메소드를 통해 다양한 미들웨어를 결합하고 미들웨어 결합 함수 <code>fn
을 반환합니다🎜- 🎜요청이 오면 < code>handleRequest 메소드가 먼저 호출됩니다. 이 메소드 완료됨: 🎜
- 이 요청에 대한 ctx 객체를 캡슐화하기 위해
createContext
메소드를 호출하세요. >그런 다음this.handleRequest(ctx, fn)
를 호출하여 요청을 처리합니다.
- 이 요청에 대한 ctx 객체를 캡슐화하기 위해
- Koa의 미들웨어 메커니즘은 커뮤니티에서 양파 모델로 생생하게 요약됩니다.
🎜 소위 양파 모델은 각 Koa 미들웨어가 양파 링의 레이어임을 의미합니다. , 요청 항목과 반환된 응답을 모두 처리할 수 있습니다. 즉, 외부 미들웨어는 내부 계층의 요청 및 응답 단계에 영향을 미칠 수 있고, 내부 미들웨어는 외부 계층의 응답 단계에만 영향을 미칠 수 있습니다. 🎜
- dispatch(n)은 n번째 미들웨어 실행에 해당하며, 사용시에는 wait next()를 통해 다음 미들웨어를 실행하기 위해 n번째 미들웨어를 "삽입"할 수 있으며, 동시에 마지막 미들웨어 실행이 완료된 후에도 여전히 실행을 재개할 수 있습니다. 즉, 어니언 모델을 통해 wait next()는 전체적으로 실행 가능한 미들웨어가 없어 스택 실행이 완료될 때까지 후속 미들웨어 호출을 제어하고, 마지막으로 다음에 실행되는 첫 번째 미들웨어에 대해 "원래 경로로 돌아갑니다". 이 접근 방식은 특히 매우 친숙해야 하는 로깅 및 오류 처리와 같은 전역 기능에 장점이 있습니다.
🎜Koa1의 미들웨어 구현은 코루틴 작업을 구현하기 위해 Generator 함수 + co 라이브러리(Promise 기반의 Generator 함수 프로세스 관리 도구)를 사용합니다. 본질적으로 Koa v1 미들웨어와 Koa v2 미들웨어의 아이디어는 유사합니다. 단, Koa v2는 Generator 함수 + co 라이브러리를 대체하기 위해 Async/Await를 사용합니다. 전체적인 구현이 더 영리하고 코드가 더 우아합니다. —— "Wolf Book"에서 🎜🎜위의 소스 코드 부분을 설명한 후 es6을 사용하여 결합할 수 있습니다. 🎜rrreee🎜use 메소드가 다른 메소드와 연결되어 있지 않은데 어떻게 실행됩니까? ? createServer를 실행한 후 채널을 설정하고 청취 기능을 탑재하는 것과 동일합니까?
이에 대해서는 Node의 소스 코드에서 더 자세히 알아보아야 할 것 같습니다... 🎜🎜🎜🎜Koa와 비교하여 Express의 원리에 대해 이야기해 보겠습니다🎜🎜🎜Node.js 프레임워크에 대해 말하자면 , Express를 잊어서는 안 됩니다. Koa와는 달리 라우팅, 정적 서버 및 템플릿 엔진과 같은 기능을 상속합니다. Koa에 비해 훨씬 "비대해졌지만" Koa보다는 프레임워크처럼 보입니다. 저자는 Express 소스 코드를 연구하여 작동 메커니즘을 간단하게 요약했습니다. 🎜
- 🎜 app.use 메소드를 통해 미들웨어를 등록하세요. 🎜
- 🎜미들웨어는 현재 경로 및 처리 방법과 일치하는 일반 정보를 포함하는 Layer 객체로 이해될 수 있습니다. 🎜
- 🎜모든 미들웨어(레이어 객체)는 스택 배열을 사용하여 저장됩니다. 🎜
- 🎜요청이 들어오면 req에서 요청 경로를 가져오고, 경로에 따라 스택에서 일치하는 레이어를 찾습니다. 구체적인 일치 프로세스는
에 의해 구현됩니다. router.handle
함수. 🎜 - 🎜
router.handle
함수는next()
메서드를 통해 비교하기 위해 각 계층을 순회합니다. 🎜next()
方法通过闭包维持了对于 Stack Index 游标的引用,当调用next()
方法时,就会从下一个中间件开始查找;- 如果比对结果为 true,则调用
layer.handle_request
方法,layer.handle_request
方法中会调用next()方法 ,实现中间件的执行。
通过上述内容,我们可以看到,Express 其实是通过 next()
方法维护了遍历中间件列表的 Index 游标,中间件每次调用next()
方法时,会通过增加 Index 游标的方式找到下一个中间件并执行。它的功能就像这样:
((req, res) => { console.log('第一个中间件'); ((req, res) => { console.log('第二个中间件'); (async(req, res) => { console.log('第三个中间件'); await sleep(2000) res.status(200).send('hello') })(req, res) console.log('第二个中间件调用结束'); })(req, res) console.log('第一个中间件调用结束') })(req, res)
如上代码,Express 中间件设计并不是一个洋葱模型,它是基于回调实现的线形模型,不利于组合,不利于互操,在设计上并不像 Koa 一样简单。而且业务代码有一定程度的侵扰,甚至会造成不同中间件间的耦合。
express的简单实现笔者已上传至腾讯微云,需要者可自行查看&下载:express的简单实现
更多编程相关知识,请访问:编程视频!!
위 내용은 nodejs 미들웨어 Koa와 Express 비교의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제









nvm을 사용하여 노드를 삭제하는 방법: 1. "nvm-setup.zip"을 다운로드하여 C 드라이브에 설치합니다. 2. "nvm -v" 명령을 통해 환경 변수를 구성하고 버전 번호를 확인합니다. install" 명령 노드 설치; 4. "nvm uninstall" 명령을 통해 설치된 노드를 삭제합니다.

파일 업로드를 처리하는 방법은 무엇입니까? 다음 글에서는 Express를 사용하여 노드 프로젝트에서 파일 업로드를 처리하는 방법을 소개하겠습니다. 도움이 되길 바랍니다.

이 기사에서는 Node의 프로세스 관리 도구인 "pm2"를 공유하고 pm2가 필요한 이유, pm2 설치 및 사용 방법에 대해 설명합니다. 모두에게 도움이 되기를 바랍니다!

Pinetwork 노드에 대한 자세한 설명 및 설치 안내서이 기사에서는 Pinetwork Ecosystem을 자세히 소개합니다. Pi 노드, Pinetwork 생태계의 주요 역할을 수행하고 설치 및 구성을위한 전체 단계를 제공합니다. Pinetwork 블록 체인 테스트 네트워크가 출시 된 후, PI 노드는 다가오는 주요 네트워크 릴리스를 준비하여 테스트에 적극적으로 참여하는 많은 개척자들의 중요한 부분이되었습니다. 아직 Pinetwork를 모른다면 Picoin이 무엇인지 참조하십시오. 리스팅 가격은 얼마입니까? PI 사용, 광업 및 보안 분석. Pinetwork 란 무엇입니까? Pinetwork 프로젝트는 2019 년에 시작되었으며 독점적 인 Cryptocurrency Pi Coin을 소유하고 있습니다. 이 프로젝트는 모든 사람이 참여할 수있는 사람을 만드는 것을 목표로합니다.

nodejs 실행 파일을 pkg로 패키징하는 방법은 무엇입니까? 다음 기사에서는 pkg를 사용하여 Node 프로젝트를 실행 파일로 패키징하는 방법을 소개합니다. 도움이 되기를 바랍니다.

"node-gyp.js"와 "Node.js"의 버전이 일치하지 않아 npm node gyp가 실패했습니다. 해결 방법: 1. "npm 캐시 clean -f"를 통해 노드 캐시를 지웁니다. 2. "npm install - g n" n 모듈을 설치합니다. 3. "n v12.21.0" 명령을 통해 "node v12.21.0" 버전을 설치합니다.

인증은 모든 웹 애플리케이션에서 가장 중요한 부분 중 하나입니다. 이 튜토리얼에서는 토큰 기반 인증 시스템과 기존 로그인 시스템과의 차이점에 대해 설명합니다. 이 튜토리얼이 끝나면 Angular와 Node.js로 작성된 완벽하게 작동하는 데모를 볼 수 있습니다. 기존 인증 시스템 토큰 기반 인증 시스템으로 넘어가기 전에 기존 인증 시스템을 살펴보겠습니다. 사용자는 로그인 양식에 사용자 이름과 비밀번호를 입력하고 로그인을 클릭합니다. 요청한 후 데이터베이스를 쿼리하여 백엔드에서 사용자를 인증합니다. 요청이 유효하면 데이터베이스에서 얻은 사용자 정보를 이용하여 세션을 생성하고, 세션 정보를 응답 헤더에 반환하여 브라우저에 세션 ID를 저장한다. 다음과 같은 애플리케이션에 대한 액세스를 제공합니다.

싱글 사인온(SSO) 시스템이란 무엇입니까? nodejs를 사용하여 구현하는 방법은 무엇입니까? 다음 글에서는 Node를 사용하여 Single Sign-On 시스템을 구현하는 방법을 소개하겠습니다. 도움이 되길 바랍니다.
