express 와 koa 미들웨어 모델 비교

6417 단어 express
원인
최근 에 koa 의 사용 을 배우 고 있 습 니 다.koa 는 상당히 기본 적 인 웹 프레임 워 크 이기 때문에 완전한 웹 응용 에 필요 한 것 은 대부분 미들웨어 형식 으로 도입 되 었 습 니 다.예 를 들 어 koa-router,koa-view 등 입 니 다.koa 의 문서 에서 언급 한 바 와 같이 koa 의 중간 부품 모델 은 express 와 다르다.koa 는 양파 형 이 고 express 는 직선 형 이다.왜 그런 지 에 대해 인터넷 의 많은 글 들 은 구체 적 으로 분석 하지 않 았 다.아니면 간단하게 async/await 의 특성 같은 거.이런 견해 의 옳 고 그 름 을 먼저 말 하지 않 고,나 에 게 있어 서 이런 견 해 는 여전히 너무 모호 하 다.그래서 나 는 소스 코드 를 통 해 양자 중간물 이 실현 하 는 원리 와 용법 의 공통점 과 차이 점 을 분석 하기 로 결정 했다.
간단하게 보기 위해 서 여기 express 는 connect 로 대체 합 니 다.
사용법
둘 다 홈 페이지(github)문 서 를 기준 으로
connect
다음은 홈 페이지 의 용법 입 니 다.

var connect = require('connect');
var http = require('http');

var app = connect();

// gzip/deflate outgoing responses
var compression = require('compression');
app.use(compression());

// store session state in browser cookie
var cookieSession = require('cookie-session');
app.use(cookieSession({
 keys: ['secret1', 'secret2']
}));

// parse urlencoded request bodies into req.body
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: false}));

// respond to all requests
app.use(function(req, res){
 res.end('Hello from Connect!
'); }); //create node.js http server and listen on port http.createServer(app).listen(3000);
문서 에 따 르 면 connect 는 간단 한 경로 기능 을 제공 합 니 다.

app.use('/foo', function fooMiddleware(req, res, next) {
 // req.url starts with "/foo"
 next();
});
app.use('/bar', function barMiddleware(req, res, next) {
 // req.url starts with "/bar"
 next();
});
connect 의 미들웨어 는 선형 이 고 next 이후 에 다음 미들웨어 를 계속 찾 습 니 다.이런 모델 은 직관 적 으로 도 잘 이해 할 수 있 습 니 다.미들웨어 는 일련의 배열 입 니 다.경로 매 칭 을 통 해 해당 하 는 경로 의 처리 방법 을 찾 는 것 이 바로 미들웨어 입 니 다.사실 connect 도 이렇게 이 루어 졌 다.
app.use 는 미들웨어 배열 에 새로운 미들웨어 를 넣 는 것 입 니 다.미들웨어 의 실행 은 개인 적 인 방법 app.handle 에 의 해 처리 되 고 express 도 마찬가지 입 니 다.
koa
connect 에 비해 koa 의 미들웨어 모델 은 직관 적 이지 않 고 인터넷 의 그림 을 빌려 표시 합 니 다.

즉,koa 가 중간 부품 을 처리 한 후에 다시 돌아 올 것 입 니 다.이것 은 우리 에 게 더욱 큰 조작 공간 을 주 었 습 니 다.koa 의 홈 페이지 인 스 턴 스 를 보 겠 습 니 다.

const Koa = require('koa');
const app = new Koa();

// x-response-time

app.use(async (ctx, next) => {
 const start = Date.now();
 await next();
 const ms = Date.now() - start;
 ctx.set('X-Response-Time', `${ms}ms`);
});

// logger

app.use(async (ctx, next) => {
 const start = Date.now();
 await next();
 const ms = Date.now() - start;
 console.log(`${ctx.method} ${ctx.url} - ${ms}`);
});

// response

app.use(async ctx => {
 ctx.body = 'Hello World';
});

app.listen(3000);

분명 한 것 은 koa 처리 미들웨어 가 await next()를 만 났 을 때 현재 미들웨어 를 중단 하고 다음 미들웨어 를 처리 한 다음 에 고 개 를 돌려 남 은 임 무 를 계속 처리 하 는 것 이다.복잡 하지만 직관 적 으로 우 리 는 은은 하고 익숙 한 느낌 이 들 것 이다.바로 리 셋 함수 가 아 닐 까?여기 서 구체 적 인 실현 방법 은 말 하지 않 지만,확실히 반전 함수 이다.async/await 의 특성 과 는 아무런 관계 가 없습니다.
소스 코드 분석
connect 와 koa 미들웨어 모델 차이 의 핵심 은 next 의 실현 에 있 습 니 다.양자 next 의 실현 을 간단하게 보 겠 습 니 다.
connect
connect 의 소스 코드 가 상당히 적 고 주석 도 200 줄 입 니 다.분명 해 보 입 니 다.connect 미들웨어 처 리 는 proto.handle 이라는 개인 적 인 방법 에 있 습 니 다.마찬가지 로 next 도 여기 서 이 루어 졌 습 니 다.

//      
var index = 0
function next(err) {


 //   
 var layer = stack[index++];

 //         
 if (!layer) {
  defer(done, err);
  return;
 }

 // route data
 var path = parseUrl(req).pathname || '/';
 var route = layer.route;

 //   
 // skip this layer if the route doesn't match
 if (path.toLowerCase().substr(0, route.length) !== route.toLowerCase()) {
  return next(err);
 }

 // call the layer handle
 call(layer.handle, route, err, req, res, next);
 }

혼 란 스 러 운 코드 를 삭제 한 후에 우 리 는 next 실현 도 매우 간결 하 다 는 것 을 볼 수 있다.재 귀적 호출 순서 로 미들웨어 를 찾 습 니 다.끊임없이 next 를 호출 합 니 다.코드 는 상당히 간단 하지만 생각 은 배 울 만하 다.
그 중에서 done 은 제3자 처리 방법 이다.다른 sub app 및 경로 처리 부분 은 모두 삭제 되 었 습 니 다.중요 한 게 아니 라
koa
koa 는 next 의 실현 을 하나의 단독 가방 으로 분리 하여 코드 가 더욱 간단 하지만 더욱 복잡 해 보 이 는 기능 을 실현 했다.

function compose (middleware) {
 return function (context, next) {
 // last called middleware #
 let index = -1
 return dispatch(0)
 function dispatch (i) {
  index = i
  try {
  return Promise.resolve(fn(context, function next () {
   return dispatch(i + 1)
  }))
  } catch (err) {
  return Promise.reject(err)
  }
 }
 }
}
위 에서 처리 한 코드 를 보면 서 어떤 학생 들 은 아직도 모 를 수도 있 습 니 다.
그럼 계속 처리 하 겠 습 니 다.

function compose (middleware) {

 return function (context, next) {
 // last called middleware #
 let index = -1
 return dispatch(0)
 function dispatch (i) {
  index = i
  let fn = middleware[i]
  if (i === middleware.length) {
  fn = next
  }
  if (!fn) return
  return fn(context, function next () {
  return dispatch(i + 1)
  })
 }
 }
}

이렇게 되면 프로그램 이 더욱 간단 해 지고 async/await 와 아무런 관계 가 없 으 니 결 과 를 보 여 주세요.

var ms = [
 function foo (ctx, next) {
 console.log('foo1')
 next()
 console.log('foo2')
 },
 function bar (ctx, next) {
 console.log('bar1')
 next()
 console.log('bar2')
 },
 function qux (ctx, next) {
 console.log('qux1')
 next()
 console.log('qux2')
 }
]

compose(ms)()
위의 프로그램 을 실행 하면 순서대로 출력 할 수 있 습 니 다.
foo1
bar1
qux1
qux2
bar2
foo2
마찬가지 로 이른바 koa 의 양파 모델 이다.여기 서 우 리 는 이러한 결론 을 얻 을 수 있다.koa 의 중간 부품 모델 은 async 나 generator 와 실제 적 인 관 계 를 가지 지 않 고 koa 가 async 우선 을 강조 할 뿐이다.미들웨어 일시 정지 라 는 것 도 리 셋 함수 의 원인 일 뿐이다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기