nodejs에서 미들웨어는 주로 HTTP 요청의 시작부터 응답이 끝날 때까지의 처리 방법을 모두 캡슐화하는 방식을 말합니다. 미들웨어의 동작은 특정 비즈니스 처리에 들어가기 전에 필터가 이를 처리하도록 하는 Java의 필터 작동 원리와 유사합니다.
이 튜토리얼의 운영 환경: windows7 시스템, nodejs 버전 12.19.0, Dell G3 컴퓨터.
NodeJS에서 미들웨어는 주로 모든 HTTP 요청 세부 사항을 캡슐화하는 방법을 말합니다. HTTP 요청에는 일반적으로 로깅, IP 필터링, 쿼리 문자열, 요청 본문 구문 분석, 쿠키 처리, 권한 확인, 매개변수 확인, 예외 처리 등과 같은 많은 작업이 포함되지만 웹 애플리케이션의 경우에는 이를 원하지 않습니다. 너무 많은 세부 처리에 노출되므로 미들웨어를 도입하여 이러한 인프라와 비즈니스 로직 간의 세부 사항을 단순화하고 격리함으로써 개발자가 개발 효율성 향상이라는 목적을 달성하기 위해 비즈니스 개발에 집중할 수 있습니다.
미들웨어의 동작은 특정 비즈니스 처리에 들어가기 전에 필터가 이를 처리하도록 하는 Java의 필터 작동 원리와 유사합니다. 작동 모델은 아래 그림에 나와 있습니다.
const middleware = (req, res, next) => { // TODO next() }
방법 1
세 가지 간단한 미들웨어를 다음과 같이 정의합니다. const middleware1 = (req, res, next) => {
console.log('middleware1 start')
next()
}
const middleware2 = (req, res, next) => {
console.log('middleware2 start')
next()
}
const middleware3 = (req, res, next) => {
console.log('middleware3 start')
next()
}
// 中间件数组
const middlewares = [middleware1, middleware2, middleware3]
function run (req, res) {
const next = () => {
// 获取中间件数组中第一个中间件
const middleware = middlewares.shift()
if (middleware) {
middleware(req, res, next)
}
}
next()
}
run() // 模拟一次请求发起
위 코드를 실행하면 다음과 같은 결과를 볼 수 있습니다. middleware1 start
middleware2 start
middleware3 start
미들웨어에 비동기 작업이 있는 경우 다음에서 끝나야 합니다. 비동기 작업 프로세스의 끝 그런 다음 next()
메서드를 호출합니다. 그렇지 않으면 미들웨어가 순서대로 실행될 수 없습니다. 미들웨어2 미들웨어 다시 작성:
const middleware2 = (req, res, next) => { console.log('middleware2 start') new Promise(resolve => { setTimeout(() => resolve(), 1000) }).then(() => { next() }) }
실행 결과는 이전과 동일하지만 미들웨어3은 미들웨어2가 비동기적으로 완료된 후 실행됩니다.
middleware1 start middleware2 start middleware3 start
통계 시간을 위한 로그 미들웨어와 같이 일부 미들웨어는 업무 처리 전에 실행되어야 할 뿐만 아니라 업무 처리 후에도 실행되어야 합니다. 방법 1의 경우, next()
가 비동기 작업인 경우 현재 미들웨어의 다른 코드를 콜백으로 실행할 수 없습니다. 따라서 next()
메서드의 후속 작업은 Promise
객체로 캡슐화될 수 있으며, next.then() 업무 처리 종료 후 콜백 형태입니다. <code>run()
메서드를 다음과 같이 다시 작성하세요.
function run (req, res) { const next = () => { const middleware = middlewares.shift() if (middleware) { // 将middleware(req, res, next)包装为Promise对象 return Promise.resolve(middleware(req, res, next)) } } next() }
미들웨어 호출 메서드를 다음과 같이 다시 작성해야 합니다. next()
方法,否则中间件不能按顺序执行。改写middleware2中间件:
const middleware1 = (req, res, next) => { console.log('middleware1 start') // 所有的中间件都应返回一个Promise对象 // Promise.resolve()方法接收中间件返回的Promise对象,供下层中间件异步控制 return next().then(() => { console.log('middleware1 end') }) }
执行结果与之前一致,不过middleware3会在middleware2异步完成后执行。
const middleware1 = (req, res, next) => { console.log('middleware1 start') // 所有的中间件都应返回一个Promise对象 // Promise.resolve()方法接收中间件返回的Promise对象,供下层中间件异步控制 return next().then((res) => { console.log("1",res) return 'middleware1 end'; }) } const middleware2 = (req, res, next) => { console.log('middleware2 start') // 所有的中间件都应返回一个Promise对象 // Promise.resolve()方法接收中间件返回的Promise对象,供下层中间件异步控制 // console.log("next()",next()) return next().then((res) => { console.log("2",res) return 'middleware2 end' }) } const middleware3 = (req, res, next) => { console.log('middleware3 start') return next().then((res) => { console.log("3",res) return 'middleware3 end' }) } const middlewares = [middleware1, middleware2, middleware3]function run (req, res) { const next = () => { const middleware = middlewares.shift() if (middleware) { // console.log("next",next) // 将middleware(req, res, next)包装为Promise对象 return Promise.resolve(middleware(req, res, next)) }else { return Promise.resolve("结束"); } } next() } run() // 模拟一次请求发起
有些中间件不止需要在业务处理前执行,还需要在业务处理后执行,比如统计时间的日志中间件。在方式一情况下,无法在next()
为异步操作时再将当前中间件的其他代码作为回调执行。因此可以将next()
方法的后续操作封装成一个Promise
对象,中间件内部就可以使用next.then()
形式完成业务处理结束后的回调。改写run()
方法如下:
const middleware1 = async (req, res, next) => { console.log('middleware1 start') let result = await next(); console.log("1",result) } const middleware2 = async (req, res, next) => { console.log('middleware2 start') let result = await next(); console.log("2",result) return 'middleware2 end'; } const middleware3 = async (req, res, next) => { console.log('middleware3 start') let result = await next(); console.log("3",result) return 'middleware3 end'; } const middlewares = [middleware1, middleware2, middleware3] function run (req, res) { const next = () => { const middleware = middlewares.shift() if (middleware) { // console.log("next",next) // 将middleware(req, res, next)包装为Promise对象 return Promise.resolve(middleware(req, res, next)) }else { return Promise.resolve("结束"); } } next() } run() // 模拟一次请求发起
中间件的调用方式需改写为:
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!') } return function (context, next) { let index = -1 return dispatch(0) function dispatch (i) { // index会在next()方法调用后累加,防止next()方法重复调用 if (i <= index) return Promise.reject(new Error('next() called multiple times')) index = i let fn = middleware[i] if (i === middleware.length) fn = next if (!fn) return Promise.resolve() try { // 核心代码 // 包装next()方法返回值为Promise对象 return Promise.resolve(fn(context, dispatch.bind(null, i + 1))); } catch (err) { // 遇到异常中断后续中间件的调用 return Promise.reject(err) } } } }rrreee
结果:
async await 实现
以上描述了中间件机制中多个异步中间件的调用流程,实际中间件机制的实现还需要考虑异常处理、路由等。
在express
框架中,中间件的实现方式为方式一,并且全局中间件和内置路由中间件中根据请求路径定义的中间件共同作用,不过无法在业务处理结束后再调用当前中间件中的代码。koa2
框架中中间件的实现方式为方式二,将next()
方法返回值封装成一个Promise
,便于后续中间件的异步流程控制,实现了koa2
框架提出的洋葱圈模型,即每一层中间件相当于一个球面,当贯穿整个模型时,实际上每一个球面会穿透两次。
koa2
rrreeerrreee
rrreee
🎜🎜위에서는 여러 미들웨어 메커니즘을 설명합니다. 비동기식 미들웨어의 호출 프로세스와 관련하여 미들웨어 메커니즘의 실제 구현에서도 예외 처리, 라우팅 등을 고려해야 합니다. 🎜🎜express
프레임워크에서는 미들웨어가 방법 1로 구현되며, 전역 미들웨어와 내장된 라우팅 미들웨어의 요청 경로에 따라 정의된 미들웨어가 함께 작동하지만 사용할 수는 없습니다. 비즈니스 처리가 완료된 후 현재 미들웨어에서 코드를 호출합니다. koa2
프레임워크의 미들웨어 구현 방법은 두 번째 방법입니다. next()
메서드의 반환 값은 Promise
로 캡슐화되어 있습니다. 후속 미들웨어 비동기 프로세스 제어는 koa2
프레임워크에서 제안한 어니언 링 모델을 구현합니다. 즉, 미들웨어의 각 레이어는 구와 동일하며 전체 모델을 관통할 때 각 구는 실제로 두 번 관통합니다. 🎜🎜🎜koa2 미들웨어 어니언링 모델🎜🎜koa2
프레임워크의 미들웨어 메커니즘은 매우 간단하고 우아합니다. 여기서는 프레임워크에서 여러 미들웨어를 결합하는 핵심 코드를 배우겠습니다. 🎜rrreee🎜koa 미들웨어 목록 주소: https://github.com/koajs/koa/wiki 🎜🎜Summary🎜🎜이 글에서는 주로 미들웨어의 개념과 미들웨어가 도입되는 이유, 미들웨어 메커니즘의 핵심 구현에 대해 소개합니다. 미들웨어 메커니즘은 웹 애플리케이션의 확장성과 구성성을 향상시킵니다. 🎜
미들웨어를 구현할 때 단일 미들웨어는 충분히 단순해야 하며 단일 책임을 져야 합니다. 각 요청은 미들웨어 관련 코드를 호출하므로 미들웨어 코드는 효율적이어야 하며 필요할 때 반복적으로 얻은 데이터를 캐시할 수 있어야 합니다. 다양한 경로에 미들웨어를 사용하는 경우 다른 미들웨어가 다른 경로에 적용된다는 점도 고려해야 합니다.
【추천 학습: "nodejs tutorial"】
위 내용은 nodejs에서 미들웨어는 무엇을 의미하나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!