익 스프 레 스 가 async/await 를 지원 하 는 방법 에 대한 자세 한 설명

8886 단어 Expressasyncawait
Node.js v8 이 발 표 됨 에 따라 Node.js 는 원래 async/await 함 수 를 지 원 했 고 웹 프레임 워 크 Koa 도 이에 따라 Koa 2 정식 판 을 발 표 했 습 니 다.async/await 미들웨어 를 지원 하여 비동기 반전 을 처리 하 는 데 큰 편 의 를 가 져 왔 습 니 다.
Koa 2 가 async/await 미들웨어 를 지원 한 이상 왜 Koa 를 직접 사용 하지 않 고 Express 를 개조 하여 async/await 미들웨어 를 지원 하 게 합 니까?Koa 2 정식 판이 발 표 된 지 얼마 되 지 않 았 기 때문에 많은 오래된 프로젝트 들 이 Express 를 사용 하기 때문에 이 를 무 너 뜨리 고 Koa 로 다시 쓸 수 없습니다.이렇게 원가 가 너무 높 지만 새로운 문법 이 가 져 온 편리 함 을 사용 하려 면 Express 를 개조 할 수 밖 에 없습니다.그리고 이런 개 조 는 반드시 업무 에 침입 하지 않 아야 합 니 다.그렇지 않 으 면 많은 번 거 로 움 을 가 져 올 수 있 습 니 다.
async/await 직접 사용 하기
Express 에서 async/await 함 수 를 직접 사용 하 는 상황 을 살 펴 보 자.

const express = require('express');
const app = express();
const { promisify } = require('util');
const { readFile } = require('fs');
const readFileAsync = promisify(readFile);
  
app.get('/', async function (req, res, next){
 const data = await readFileAsync('./package.json');
 res.send(data.toString());
});
// Error Handler
app.use(function (err, req, res, next){
 console.error('Error:', err);
 res.status(500).send('Service Error');
});
  
app.listen(3000, '127.0.0.1', function (){
 console.log(`Server running at http://${this.address().address }:${this.address().port }/`);
});
위 에 서 는 Express 를 개조 하지 않 고 async/await 함수 로 요청 을 처리 합 니 다.요청 할 때http://127.0.0.1:3000/ 요청 이 정상적으로 요청 되 고 응답 도 정상적으로 응답 할 수 있 음 을 발 견 했 습 니 다.이렇게 하면 Express 에 어떠한 개조 도 하지 않 고 async/await 함 수 를 직접 사용 할 수 있 는 것 같 습 니 다.그러나 async/await 함수 에서 오류 가 발생 하면 우리 의 오류 처리 미들웨어 에 의 해 처 리 될 수 있 습 니까?현재 우 리 는 이전에 읽 은 package.json 을 age.json 으로 바 꾸 는 등 존재 하지 않 는 파일 을 읽 으 러 갑 니 다.

app.get('/', async function (req, res, next){
 const data = await readFileAsync('./age.json');
 res.send(data.toString());
});
지금 저희 가 부탁 하 러 가 겠 습 니 다.http://127.0.0.1:3000/ 요청 이 늦 어 져 응답 하지 못 하 는 것 을 발견 하면 시간 이 초 과 됩 니 다.터미널 에서 다음 과 같은 오 류 를 보 고 했 습 니 다.

오류 가 미들웨어 에 의 해 처리 되 지 않 고 unhandled Rejection 이상 을 던 진 것 을 발 견 했 습 니 다.지금 우리 가 try/catch 로 수 동 으로 오 류 를 포착 하면 어떤 상황 일 까요?

app.get('/', async function (req, res, next){
 try {
  const data = await readFileAsync('./age.json');
  res.send(datas.toString());
 } catch(e) {
  next(e);
 }
});
요청 이 잘못된 처리 미들웨어 로 처 리 된 것 을 발견 한 것 은 우리 가 수 동 으로 오 류 를 포착 하 는 것 이 가능 하 다 는 것 을 의미한다.그러나 모든 미들웨어 나 요청 처리 함수 에 try/catch 를 추가 하 는 것 도 너무 우아 하지 않 고 업무 코드 에 어느 정도 침입 성 이 있 으 며 코드 도 보기 흉 하 다.그래서 async/await 함 수 를 직접 사용 하 는 실험 을 통 해 우 리 는 Express 를 개조 하 는 방향 이 바로 async/await 함수 에서 던 진 오 류 를 받 아들 일 수 있 고 업무 코드 에 침입 성 이 없다 는 것 을 발견 했다.
익 스프 레 스 개조
Express 에 서 는 두 가지 방식 으로 경로 와 미들웨어 를 처리 합 니 다.하 나 는 Express 를 통 해 만 든 app 입 니 다.app 에 미들웨어 와 처리 경 로 를 직접 추가 합 니 다.아래 와 같 습 니 다.

const express = require('express');
const app = express();
  
app.use(function (req, res, next){
 next();
});
app.get('/', function (req, res, next){
 res.send('hello, world');
});
app.post('/', function (req, res, next){
 res.send('hello, world');
});
  
app.listen(3000, '127.0.0.1', function (){
 console.log(`Server running at http://${this.address().address }:${this.address().port }/`);
});
다른 하 나 는 Express 의 Router 를 통 해 만 든 경로 인 스 턴 스 입 니 다.경로 인 스 턴 스 에 미들웨어 와 처리 경 로 를 직접 추가 합 니 다.아래 와 같이:

const express = require('express');
const app = express();
const router = new express.Router();
app.use(router);
  
router.get('/', function (req, res, next){
 res.send('hello, world');
});
router.post('/', function (req, res, next){
 res.send('hello, world');
});
  
app.listen(3000, '127.0.0.1', function (){
 console.log(`Server running at http://${this.address().address }:${this.address().port }/`);
});
이 두 가지 방법 을 혼합 해서 사용 할 수 있 습 니 다.이제 app.get('/',async function(req,res,next){})과 같은 함 수 를 어떻게 해 야 async 함수 가 던 진 오 류 를 통일 적 으로 처리 할 수 있 는 지 생각해 보 겠 습 니 다.오 류 를 통일 적 으로 처리 하려 면 next(err)를 호출 하여 오 류 를 처리 미들웨어 로 전달 해 야 합 니 다.또한 async 함수 가 Promise 로 되 돌아 오기 때문에 이러한 asyncFn().then().catch(function(err){next(err)})가 있 을 것 입 니 다.이렇게 개조 하면 다음 과 같은 코드 가 있 습 니 다.

app.get = function (...data){
 const params = [];
 for (let item of data) {
  if (Object.prototype.toString.call(item) !== '[object AsyncFunction]') {
   params.push(item);
   continue;
  }
  const handle = function (...data){
   const [ req, res, next ] = data;
   item(req, res, next).then(next).catch(next);
  };
  params.push(handle);
 }
 app.get(...params)
}
위의 이 코드 에서 우 리 는 app.get()이라는 함수 의 매개 변 수 를 판단 합 니 다.async 함수 가 있 으 면 item(req,res,next).then(next).catch(next)를 사용 합 니 다.함수 에서 던 진 오 류 를 포착 하고 오류 처리 미들웨어 로 전달 할 수 있 습 니 다.그러나 이 코드 는 마지막 에 app.get()을 호출 하 는 뚜렷 한 오류 가 있 습 니 다.그러면 재 귀 되 고 app.get 의 기능 을 파괴 하 며 요청 을 처리 할 수 없 기 때문에 계속 개조 해 야 합 니 다.
우 리 는 이전에 Express 의 두 가지 처리 경로 와 중간 부품 의 방식 을 혼용 할 수 있다 고 말 했다.그러면 우 리 는 이 두 가지 방식 을 혼용 하여 재 귀 를 피 할 것 이다.코드 는 다음 과 같다.

const express = require('express');
const app = express();
const router = new express.Router();
app.use(router);
  
app.get = function (...data){
 const params = [];
 for (let item of data) {
  if (Object.prototype.toString.call(item) !== '[object AsyncFunction]') {
   params.push(item);
   continue;
  }
  const handle = function (...data){
   const [ req, res, next ] = data;
   item(req, res, next).then(next).catch(next);
  };
  params.push(handle);
 }
 router.get(...params)
}
위 에서 처럼 개조 한 후에 모든 것 이 정상적으로 일 할 수 있 을 것 같 아서 요 구 를 정상적으로 처리 할 수 있 게 되 었 다.그러나 Express 의 소스 코드 를 보면 app.get()방법 을 파괴 한 것 을 알 수 있 습 니 다.app.get()은 경로 처리 뿐만 아니 라 응용 설정 도 얻 을 수 있 기 때 문 입 니 다.Express 에서 대응 하 는 소스 코드 는 다음 과 같 습 니 다.

methods.forEach(function(method){
 app[method] = function(path){
  if (method === 'get' && arguments.length === 1) {
   // app.get(setting)
   return this.set(path);
  }
  
  this.lazyrouter();
  
  var route = this._router.route(path);
  route[method].apply(route, slice.call(arguments, 1));
  return this;
 };
});
그래서 개조 할 때 도 app.get 에 대해 특별한 처 리 를 해 야 합 니 다.실제 응용 프로그램 에서 우 리 는 get 요청 뿐만 아니 라 post,put,delete 등 요청 도 있 기 때문에 우리 가 최종 적 으로 개조 한 코드 는 다음 과 같다.

const { promisify } = require('util');
const { readFile } = require('fs');
const readFileAsync = promisify(readFile);
const express = require('express');
const app = express();
const router = new express.Router();
const methods = [ 'get', 'post', 'put', 'delete' ];
app.use(router);
  
for (let method of methods) {
 app[method] = function (...data){
  if (method === 'get' && data.length === 1) return app.set(data[0]);

  const params = [];
  for (let item of data) {
   if (Object.prototype.toString.call(item) !== '[object AsyncFunction]') {
    params.push(item);
    continue;
   }
   const handle = function (...data){
    const [ req, res, next ] = data;
    item(req, res, next).then(next).catch(next);
   };
   params.push(handle);
  }
  router[method](...params);
 };
}
   
app.get('/', async function (req, res, next){
 const data = await readFileAsync('./package.json');
 res.send(data.toString());
});
   
app.post('/', async function (req, res, next){
 const data = await readFileAsync('./age.json');
 res.send(data.toString());
});
  
router.use(function (err, req, res, next){
 console.error('Error:', err);
 res.status(500).send('Service Error');
}); 
   
app.listen(3000, '127.0.0.1', function (){
 console.log(`Server running at http://${this.address().address }:${this.address().port }/`);
});

이제 개조 가 끝 났 습 니 다.우 리 는 코드 를 조금 만 추가 하면 async function 을 handler 로 처리 할 수 있 습 니 다.업무 에 도 침입 성 이 없고 던 진 오류 도 오류 처리 미들웨어 로 전달 할 수 있 습 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기