Koa 학습 01 Koa 소개 및 기본 사용(라우팅, 정적 리소스 호스팅, 미들웨어)

코아 소개

  • Koa는 Express 뒤에 있는 동일한 사람들이 구축한 새로운 웹 프레임워크로 , 웹 애플리케이션 및 API 개발을 위한 더 작고 표현력이 풍부하며 강력한 빌딩 블록이 되는 것을 목표로 합니다.
    • 공식 홈페이지: https://koajs.com/
    • GitHub 저장소: https://github.com/koajs/koa
    • 번역된 중국어 웹사이트: https://koa.bootcss.com/
  • Koa의 원리와 내부 구조는 Express와 매우 유사하지만 구문과 내부 구조가 업그레이드되었습니다.
  • Koa 는 내부적으로 ES6로 작성되었으며 차세대 Node.js 웹 프레임워크라고 주장합니다.
  • 주요 기능은 비동기 함수를 사용하여 콜백 함수를 폐기하도록 돕는 것입니다.
    • Koa 1은 CO 모듈과 결합된 ES2015의 Generator 제너레이터 기능을 기반으로 합니다.
    • Koa 2는 Generator 및 co를 완전히 포기하고 ES2017에서 async/await 기능으로 업그레이드합니다.
  • Koa는 최신 비동기 처리 방식을 기반으로 하기 때문에 Koa를 사용하여 예외를 처리하기가 더 쉽습니다.
  • 컨텍스트 개체는 Koa에서 제공됩니다.
    • Koa는 Nodejs에서 req 및 res를 래핑하고 확장합니다.
    • Express는 req와 res를 확장합니다.
  • Koa는 미들웨어를 번들로 제공하지 않지만 서버 측 애플리케이션을 빠르고 즐겁게 작성하는 데 도움이 되는 일련의 우아한 방법을 제공합니다.
    • Koa 자체는 라우팅, 템플릿, 파일 전송, JSONP 및 기타 기능을 지원하지 않으므로 해당 미들웨어를 별도로 설치해야 합니다.
  • Koa를 기반으로 하는 많은 개발 도구/프레임워크가 있습니다.
    • Egg.js - 엔터프라이즈 웹 개발 프레임워크
    • 빌드 도구 Vite - Vue 3 빌드 도구
  • Koa vs Express 공식 비교
  • 다른 의견
    • koa 2는 사용하기 쉽고 디자인 면에서 장점이 있습니다. 장점은 더 강력한 기능을 구현할 수 있는 것이 아니라 더 간단하게 완성할 수 있다는 점입니다.
    • Koa 2 커뮤니티는 표현하기가 훨씬 열등합니다.
    • koa 1은 koa 2와 이념적으로 일치하지만 koa 2 구현이 더 예쁘다.
  • Awesome Koa - 일부 Koa 관련 리소스, 자습서, 미들웨어 등을 포함하는 타사 창고입니다.

Koa의 기본 사용법

Koa로 HTTP 서비스 시작

npm init -y
# 安装 koa
npm i koa
// app.js
const Koa = require('koa')

const app = new Koa()

// Koa 没有路由系统,只有中间件功能
// ctx:context 上下文对象,包含请求和响应相关方法
app.use(ctx => {
    
    
  // 发送响应
  ctx.body = 'Hello Koa'
})

app.listen(3000, () => {
    
    
  console.log('server is running on http://localhost:3000')
})

nodemon ./app.js

Koa의 라우팅

Koa 자체에는 자체 라우팅 기능이 없기 때문에 서로 다른 요청 경로를 분산 처리하려면 프로세스를 수동으로 코딩해야 합니다.

app.use(ctx => {
    
    
  const path = ctx.path
  console.log(path);
  if (path === '/') {
    
    
    ctx.body = 'home page'
  } else if (path === '/foo') {
    
    
    ctx.body = 'foo page'
  } else {
    
    
    ctx.body = '404 Not Found.'
  }
})

실제로 Koa는 라우팅 기능을 포함하여 일부 기능을 npm 패키지에 개별적으로 캡슐화합니다.

Koa.js(github.com) 에서 웨어하우스를 검색하면 여러 공식 라우팅 툴킷을 찾을 수 있으며 Express 스타일의 메소드( 등)를 사용하는 koajs / routerroute 사용을 권장합니다 .app.getapp.post

# 安装
npm i @koa/router
// app.js
const Koa = require('koa')
const Router = require('@koa/router')

const app = new Koa()
const router = new Router()

router.get('/', ctx => {
    
    
  ctx.body = 'home page'
})

router.post('/', ctx => {
    
    
  ctx.body = 'post /'
})

router.get('/foo', ctx => {
    
    
  ctx.body = 'foo page'
})

router.get('/bar', ctx => {
    
    
  // 重定向
  ctx.redirect('/foo')
})

router.get('/users/:id', ctx => {
    
    
  ctx.body = ctx.params
})

app
  // 挂载路由配置
  .use(router.routes())
  // 配置允许的请求方法:OPTIONS 请求的 Allow 请求头
  .use(router.allowedMethods())

app.listen(3000, () => {
    
    
  console.log('server is running on http://localhost:3000')
})

Koa의 정적 리소스 호스팅

koajs/static 모듈은 정적 리소스 호스팅 기능을 캡슐화합니다.

npm i koa-static
// app.js
const Koa = require('koa')
const static = require('koa-static')
const path = require('path')

const app = new Koa()

// http://localhost:3000/css/style.css 访问 /public/css/style.css 文件
app.use(static(path.join(__dirname, './public')))

app.listen(3000, () => {
    
    
  console.log('server is running on http://localhost:3000')
})

Koa의 미들웨어는 첫 번째 매개 변수를 통해 요청 경로를 설정할 수 없으므로 다음과 같은 방법으로 정적 리소스 디렉터리에 가상 경로를 추가하면 오류가 발생합니다.

app.use('/public', static(path.join(__dirname, './public')))

Koa의 다른 모듈인 koajs/mount를 사용하여 Koa 애플리케이션 또는 미들웨어를 지정된 경로에 마운트할 수 있습니다.

npm i koa-mount
// mount(<路径>, <中间件>)
app.use(mount('/public', static(path.join(__dirname, './public'))))

코아 미들웨어

미들웨어 실행 스택

Express와 마찬가지로 Koa의 가장 큰 특징은 전적으로 미들웨어에 구축된 웹 프레임워크입니다.

Koa 미들웨어와 Express 미들웨어에는 큰 차이가 있습니다. Koa 미들웨어는 완전히 양파 모델을 기반으로 합니다(그림 참조).

여기에 이미지 설명 삽입

  • 여러 개의 미들웨어가 스택 구조(중간 스택)를 형성하고 "선입선출"의 순서로 실행됩니다.
  • 가장 바깥쪽 미들웨어가 먼저 실행됩니다.
  • 함수를 호출 하면 next다음 미들웨어에 실행권한이 넘어가게 됩니다.
  • 가장 안쪽의 미들웨어가 마지막으로 실행
  • 실행 완료 후 실행 권한은 상위 레이어의 미들웨어로 반환
  • 가장 바깥쪽 미들웨어가 실행 권한을 철회한 후 다음 함수 뒤의 코드를 실행합니다.

코드를 통해 미들웨어의 스택 구조를 살펴보겠습니다.

const one = (ctx, next) => {
    
    
  console.log('>> one')
  next()
  console.log('<< one')
}

const two = (ctx, next) => {
    
    
  console.log('>> two')
  next()
  console.log('<< two')
}

const three = (ctx, next) => {
    
    
  console.log('>> three')
  next()
  console.log('<< three')
}

app.use(one)
app.use(two)
app.use(three)

인쇄 결과:

>> one
>> two
>> three
<< three
<< two
<< one

미들웨어 내부에서 함수가 호출되지 않으면 next실행 권한이 전달되지 않습니다. 예를 들어 two함수에 주석을 달아 next()결과를 인쇄합니다.

>> one
>> two
<< two
<< one

비동기 미들웨어

지금까지 미들웨어의 모든 예는 동기식이며 비동기식 작업을 포함하지 않습니다. 비동기 작업(예: 데이터베이스 읽기, 파일 읽기)이 있는 경우 미들웨어는 비동기 함수로 작성되어야 합니다.

const Koa = require('koa')
const path = require('path')
const fsPromises = require('fs').promises

const app = new Koa()

app.use(async (ctx, next) => {
    
    
  const data = await fsPromises.readFile(path.join(__dirname, './views/index.html'))
  // 设置 content-type 为 text/html
  // 或者在读取文件的时候设置编码为 `utf8`
  ctx.type = 'html'
  ctx.body = data
  next()
})

app.listen(3000, () => {
    
    
  console.log('server is running on http://localhost:3000')
})

여러 미들웨어 결합

기본적으로 Koa는 미들웨어를 하나씩만 마운트할 수 있습니다.

app.use(one)
app.use(two)
app.use(three)

미들웨어 조합 도구 koajs/compose를 사용하여 여러 미들웨어를 하나의 미들웨어로 결합하여 마운트할 수 있습니다.

npm i koa-compose
app.use(compose([one, two, three]))

글로벌 예외 처리

오류를 포착하고 수동으로 응답하는 미들웨어는 다음과 같습니다.

app.use(ctx => {
    
    
  try {
    
    
    JSON.parse('string')
    ctx.body = 'Hello Koa'
  } catch (error) {
    
    
    ctx.response.status = 500
    ctx.response.body = '服务端内部错误'
  }
})

ctx.throwKoa에서 제공하는 바로 가기 방법을 사용하여 오류에 응답할 수도 있습니다 .

app.use(ctx => {
    
    
  try {
    
    
    JSON.parse('string')
    ctx.body = 'Hello Koa'
  } catch (error) {
    
    
    // ctx.response.status = 500
    // ctx.response.body = '服务端内部错误'

    // ctx.throw(500) // body => Internal Server Error
    ctx.throw(404) //  body => Not Found
  }
})

위의 예는 단일 미들웨어에 대한 오류 캡처 프로세스입니다.프로그램에서 예외를 균일하게 처리하려면 어니언 미들웨어 모델을 사용하여 가장 바깥쪽 레이어에서 오류를 잡기 위한 코드를 작성해야 합니다.

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

// 最外层添加异常捕获的中间件
app.use((ctx, next) => {
    
    
  try {
    
    
    next()
  } catch (error) {
    
    
    ctx.response.status = 500
    ctx.response.body = error.message
  }
})

app.use(ctx => {
    
    
  JSON.parse('string')
  ctx.body = 'Hello Koa'
})

...

Koa가 오류를 처리하는 방식이 Express보다 더 편리하다는 것을 알 수 있습니다. 모든 미들웨어에서 try-catch오류를 잡아서 next.

위의 모든 예제는 동기식 미들웨어를 사용한다는 점에 유의하십시오.비동기식 미들웨어인 경우 다음에서 try-catch사용해야 합니다 await.

// 最外层添加异常捕获的中间件
app.use(async (ctx, next) => {
    
    
  try {
    
    
    // 使用 await 等待下一个中间件处理完成
    await next()
  } catch (error) {
    
    
    ctx.response.status = 500
    ctx.response.body = error.message
  }
})

// 同步中间件:A
app.use((ctx, next) => {
    
    
  next()
})

// 异步中间件:B
app.use(async ctx => {
    
    
  // 读取不存在的文件
  await fsPromises.readFile('file.txt')
})

그러나 상위 미들웨어 A는 동기식이며 하위 미들웨어의 결과를 기다리지 않고 가장 바깥쪽 오류 처리 미들웨어는 await미들웨어 A의 실행 결과이기 때문에 이것은 미들웨어 B의 오류를 포착하지 못합니다.

해결책은 다음과 같습니다.

// 方案一,同步中间件返回下层中间件的执行结果
// 同步中间件:A
app.use((ctx, next) => {
    
    
  return next()
})
// 方案二,将同步中间件改为异步中间件,await next()
// 同步中间件:A
app.use(async (ctx, next) => {
    
    
  await next()
})

이것은 JS의 Promise 구문 문제이며 Koa 및 미들웨어와 관련이 없습니다.

제안: 모든 미들웨어에 비동기 함수를 사용하고 await를 asycn사용하십시오 .awaitnext()

비동기 처리의 또 다른 방법

외부 미들웨어를 사용하여 오류를 잡는 것 외에도 Koa는 error이벤트를 수신하여 오류를 잡을 수도 있습니다.

// 可以在任意位置监听事件
app.on('error', err => {
    
    
  console.log(err)
})

**참고:** 외부 미들웨어는 try-catch오류를 포착하고 처리하는 데 사용되며 error이벤트는 트리거되지 않습니다.

예외를 처리하고 미들웨어에서 이벤트를 트리거하려는 경우 error미들웨어에서 수동으로 error이벤트를 트리거할 수 있습니다.

// 最外层添加异常捕获的中间件
app.use(async (ctx, next) => {
    
    
  try {
    
    
    await next()
  } catch (error) {
    
    
    ctx.response.status = 500
    ctx.response.body = error.message
    // 触发 error 事件
    ctx.app.emit('error', error, ctx)
  }
})

실제 프로젝트에서는 둘 중 하나를 사용할 수 있습니다(미들웨어 권장).

추천

출처blog.csdn.net/u012961419/article/details/123915439