抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

特性

  • 原理和内部结构和express很像,但是进行了语法和内部结构的升级
  • 使用ES6编写,下一代web框架
  • 利用async函数,丢弃回调函数
  • Koa1基于ES6的Generator结合co,Koa2摈弃生成器函数和co,升级为ES8中的async/await函数
  • Koa提供了ctx上下文对象, ctx上也挂载了req,res;express只是对req,res的扩展
  • Koa没有路由系统,只有中间件功能
  • 很多工具基于Koa,Egg.js, vite
  • Koa2社区不如express
  • awesome-koa

Koa启动一个http服务

npm i koa
const Koa = require('koa')

const app = new Koa()

app.use(ctx => {
  ctx.body = 'hello world'
})

app.listen(3000, () => {
  console.log('http://localhost:3000')
})
  • 对ctx.res的处理,绕过Koa,不被支持
  • 别名:访问ctx.request上的某些属性和方法同ctx上直接访问等效,如ctx.header === ctx.request.header; response同理

Koa中的路由
Koa默认没有提供路由,想根据不同路由分发不同功能需要自己处理。
可以借助中间件实现,关昂提供了两个包,route, router(推荐使用,同express使用风格类似)

安装使用

npm i @koa/router
const Koa = require('koa')
const Router = require('@koa/router')

// 支持动态路径,如/user/:id,通过ctx.params获取
router.get('/', ctx =>{
  ctx.body = 'home'
})

const app = new Koa()

app.use(router.routes())
    .use(router.allowedMethods)

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

静态资源管理
koa-static封装了静态资源的处理

npm i koa-static
const static = require('koa-static')
const path = require('path')

// 当前文件执行路径下的public中的资源会被映射到服务根目录/下
app.use(static('./public'))    // 使用绝对路径安全点

这个包不能像express的api那样设置虚拟路径,需要引入第三方包mount
npm i koa-amount

app.use(
  mount('/static', static('./public'))
)

路由重定向
ctx.redirect(), 会以302状态码返回到客户端,并且带上响应头location, 只能针对同步请求,不能处理异步请求
中间件
所有中间件都是通过app实例use进行挂载生效的, 洋葱模型

  • 多个中间件形成栈结构,最外层中间件首先执行,最内存中间件最后执行
  • 调用next函数,执行权交给下一个中间件
  • 执行结束后,执行权交回上一层中间件
  • 最外层中间件收回执行权以后,执行next函数后的代码,参考egg

异步中间件

const util = require('util')    // util/promisify,异步函数同步化
app.use(async (ctx) => {
  // ...异步代码
})

多个中间件的合并

app.use(a), app.use(b), ….这种比较恶心
可以借助koa-compose合并中间件
最内层的中间件不用next()

const compose = require('koa-compose')

app.use(compose([a, b, c]))

中间件异常处理
通过try…catch, ctx.throw抛出http状态码可以快捷抛出
每个中间件用try…catch包裹,这是express中的处理风格,最后挂载一个错误处理中间件。
koa中不是这么处理,在最外层try…catch捕获异常即可,后面的中间件都不用再捕获错误了,如果是异步抛出的异常,之前的所有中间件, 包括错误处理中间件中的next前面加上await或者return

Koa中的异常处理
app.on(‘error’), 书写位置不用在最外层,也有和以上中间件异常处理一样的问题,如果有中间件的next没有加await或return, app.on(‘error’)是捕获不到这种异步错误
和中间件的异常处理同时出现时, 这里不会执行,如果想要error事件被触发,可以这么做

app.use(async (ctx, next) =>{
    try {
    await next()
  } catch(err) {
    ctx.status = 500
    ctx.body = err.message
    ctx.app.emit('error', err, ctx)
  }

})

Koa源码结构
Koa导出的是一个继承自Emitter的Application类

实现一个简单的Koa

const http = require('http')

class Applicaton {
  constructor () {
    this.middleware = [] // 保存中间件
  }
  listen (...args) {
    http.createServer(this.callback())
    server.listen(...args)
  }

  use(fn) {
    this.middleware.push(fn)
  }

  compose (middleware) {
    return function (){
      const dispatch = index => {
        if(index >= middleware.length) return Promise.resolve()
        const fn = middleware[index]
        return Proise.resolve(
          fn({}, () => dispatch(index + 1))        // fn就是中间件处理函数
        )
      }

      return dispatch(0)
    }
  }

  callback () {

    const handleRequest = (req, res) => {

    }
    return handleRequest
  }

}

module.exports = Applicaton

用户交流区