nodejs(十)Koa使用教程

4,575 阅读4分钟

0. 准备

  1. 检查Node版本,使用koa需要使用 7.6以上的版本

    node -v
    

一. 基本使用

1.1 搭建http服务器

使用koa搭建http服务器很简单,只需要如下三步,即可

//demo01.js
const Koa = require('koa')
const app = new Koa()

app.listen(3000)

然后使用node命令运行该文件即可

node buildHttp.js

打开浏览器,我们输入 http://loaclhost:3000访问,页面显示Not Found,这是因为我们并没有告诉Koa应该显示什么内容

1.2 Context对象

Koa提供一个Context对象,表示一次对话的上下文(包括http的请求对象和响应对象),通过操作这个对象,就可以控制返回给用户的内容

Context.response.body 属性就是发送给用户的内容

//demo02.js
const Koa = require('koa')
const app = new Koa()

var main = ctx => {
    ctx.response.body = 'hello world'
}

app.use(main)
app.listen(3000)

其中main方法就是用来设置响应内容,然后通过 app.use方法使用该函数

使用 node命令运行该文件,再次访问浏览器

1.3 http Response的类型

Koa的默认返回类型是 text/plain,我们可以通过 ctx.request.accepts判断一下客户希望接收什么类型的数据(根据HTTP请求中的Accept字段),然后通过 ctx.response.type指定返回值类型

// demo03.js
  
const Koa = require('koa');
const app = new Koa();

const main = ctx => {
  if (ctx.request.accepts('xml')) {
    ctx.response.type = 'xml';
    ctx.response.body = '<data>Hello World</data>';
  } else if (ctx.request.accepts('json')) {
    ctx.response.type = 'json';
    ctx.response.body = { data: 'Hello World' };
  } else if (ctx.request.accepts('html')) {
    ctx.response.type = 'html';
    ctx.response.body = '<p>Hello World</p>';
  } else {
    ctx.response.type = 'text';
    ctx.response.body = 'Hello World';
  }
};

app.use(main);
app.listen(3000);

1.4 网页模版

实际开发过程中,返回给用户网页一般都是写成模版文件,可以让koa先获取模版,然后将模版返回给用户

// demo04.js
const Koa = require('koa')
const app = new Koa()
const fs = require('fs')

var main = ctx => {
    ctx.response.type = 'html'
    ctx.response.body = fs.createReadStream('./views/template.html')
}

app.use(main)
app.listen(3000)

二. 路由

2.1 原生路由

原生路由即我们手写的路由,通过对URL的判断,返回給用户不同的内容,具体实现如下

// demo05.js
const Koa = require('koa')
const app = new Koa()

var main = ctx => {
    if(ctx.request.path == '/'){
        ctx.response.type = 'html'
        ctx.response.body = 'home page'
    }else if(ctx.request.path === '/about'){
        ctx.response.type = 'html'
        ctx.response.body = '<h1>about page</h1>'
    }else{
        ctx.response.type = 'html'
        ctx.response.body = '<h1>no set url resource</h1>'
    }
}

app.use(main)

app.listen(3000)

2.2 koa-router 模块

原生路由用起来不太方便,于是我们封装了 koa-route模版

// demo06.js

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

var home = ctx => {
    ctx.response.type = 'html'
    ctx.response.body = `<a href='#'>Home page</a>`
}

var about = ctx => {
    ctx.response.type = 'html'
    ctx.response.body = `<a href='#'>About page</a>`
}

app.use(route.get('/',home))
app.use(route.get('/about',about))

app.listen(3000)
  • 上面代码中,/路径的处理函数是 home,/about路径的处理函数是 about

2.3 静态资源

如果网站提供了静态资源(图片,字体,样式,脚本),为他们一个个写路由就很麻烦,也没必要

koa-static 模块封装了这部分的请求

//demo07.js
const Koa = require('koa')
const app = new Koa()
const serve = require('koa-static')
const path = require('path')

const main = serve(path.join(__dirname))

app.use(main)


app.listen(3000)
  • 设置之后可以直接在URL地址中输入静态资源文件名进行访问

2.4 重定向

有些场合,服务器需要重定向,

ctx.response.redirect() 方法可以发出一个302跳转,将用户导向另一个路由

// demo08.js
const Koa = require('koa')
const app = new Koa()
const route = require('koa-route')

var home = ctx => {
    ctx.response.type = 'html'
    ctx.response.body = `<a href='#'>Home page</a>`
}

var about = ctx => {
    ctx.response.type = 'html'
    ctx.response.body = `<a href='#'>About page</a>`
}

var redict = ctx => {
    ctx.response.redirect('/')
}

app.use(route.get('/',home))
app.use(route.get('/about',about))
app.use(route.get('/redict',redict))

app.listen(3000)

三,中间件

3.1 logger功能

koa的最大特色,也是最重要的一个设计,就是中间件。

来看如下一个案例:实现打印日志的功能,

// demo09.js
const Koa = require('koa')
const app = new Koa()

var main = ctx => {
    console.log(`${Date.now()}--${ctx.request.method}--${ctx.request.url}`)
    ctx.response.body = 'hello world'
}

app.use(main)
app.listen(3000)

3.2 中间件的概念

在如上的案例基础上,我们可以把日志功能抽离出来,行成一个单独的函数

抽离出来的单独的函数,就叫做中间件

**含义:**处于Http Request和Http Response之间,用来实现某种中间功能,然后使用 app.use方法来使用中间件

**参数:**每个中间件默认接受两个参数

  • ctx:上下文对象
  • next:第二个参数是next函数。只要调用next函数,就可以把执行权交给下一个中间件
const logger = (ctx,next) => {
	 console.log(`${Date.now()}--${ctx.request.method}--${ctx.request.url}`)
	 next()
}

app.use(logger)

3.3 中间件栈

多个中间件会行成一个栈结构,以先进后出的顺序执行

  • 执行顺序如下

    1. 最外层的中间件首先执行。
    2. 调用next函数,把执行权交给下一个中间件
    3. ...
    4. 最内层的中间件最后执行
    5. 执行结束后,把执行权交回上一层的中间件
    6. ...
    7. 最外层的中间件收回执行权之后,执行next函数之后的代码
    
  • 示例

    // demo10.js
    const Koa = require('koa')
    const app = new Koa()
    
    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)
    
    app.listen(3000)
    
  • 运行结果

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

3.4 异步中间栈

如果有异步操作,中间件就必须写成 async函数

// demo11.js
const Koa = require('koa')
const app = new Koa()
const fs = require('fs')

var main = async function(ctx,next){
    ctx.response.type = 'html'
    ctx.response.body = await fs.readFileSync('./views/template.html','utf-8')
}

app.use(main)

app.listen(3000)

3.5 中间件的合成

koa-compose 模块可以将多个中间件合成为一个

// demo12.js
const Koa = require('koa')
const app = new Koa()
const compose = require('koa-compose')

const logger = (ctx,next) => {
    console.log(`${Date.now()}${ctx.request.method}${ctx.request.url}`)
    next()
}

const main = (ctx,next) => {
    ctx.response.body =  'hello world'
}

const middleWares = compose([logger,main])
app.use(middleWares)
app.listen(3000)

注:本文参考阮一峰:koa框架教程