基于node.js的开发框架 — Koa

485 阅读10分钟

一、简介

Koa 基于nodeJs平台的下一代web开发框架,由 Express 幕后的原班人马打造,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。使用 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件,它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。目前有 1.x 和 2.x 两个大的版本其中 2.x 版本使用了 Node.js v7.6.0 之后支持的 async await 语法糖,提供了更优雅的异步编程模式。

二、Koa的核心概念

Koa到底是做什么事情的?Koa最主要最核心的是实现http协议的处理,它有三个大的核心概念:

  1. Koa Application:主程序
  2. Context:上下文
  3. Request、Response: 请求和响应

三、基本用法

【1】准备工作

// 1.Koa必须使用7.6以上的node版本,检查node版本,低于要求的话就升级node
$ node -v 

// 2.创建一个 my_koa 文件夹,生成package.json文件
$ npm init -y

// 3.安装koa依赖
$ npm install --save koa

【2】编写代码

在my_koa文件夹下创建一个index.js入口文件,接下来我们用koa架设一个http服务

// index.js文件
const Koa = require('Koa');  // 引入Koa
const app = new Koa();  // 创建Koa实例,定义Application

// 使用use方法来处理上下文
app.use(async ctx => {  
  // ctx是包含整个应用的上下文,可以对用户的请求做一些处理
  ctx.body = 'hello, World!'
});

app.listen(3000);  // 设置端口号,让Koa应用运行在3000端口上

在index.js文件编写完上面代码之后,在文件目录下打开终端,输入 node index.js 来运行该文件。

然后打开浏览器输入:localhost:3000 ,就可以看到我们输出的结果啦

四、Application(应用程序)

Koa 应用程序是一个包含一组中间件函数的对象,它是按照类似堆栈的方式组织和执行的。 Koa 类似于你可能遇到过的许多其他中间件系统。

【1】app.listen():绑定一个端口服务器作为程序入口,可以绑定多个。以下是一个无作用的 Koa 应用程序被绑定到 3000 端口

const Koa = require('koa');
const app = new Koa();
app.listen(3000); 

// app.listen(3000)是以下方法的语法糖

const http = require('http');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);

【2】app.use(function):将给定的中间件方法添加到此应用程序,app.use() 返回 this,因此可以链式表达

app.use(someMiddleware)
app.use(someOtherMiddleware)
app.listen(3000)

// 等同于

app.use(someMiddleware).use(someOtherMiddleware).listen(3000)

【3】app.keys= : 设置签名的 Cookie 密钥

app.keys = ['im a newer secret', 'i like turtle'];
app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256');

【4】app.context: 是从其创建 ctx 的原型。您可以通过编辑 app.context 为 ctx 添加其他属性

app.context.db = db();

app.use(async ctx => {
  console.log(ctx.db);
});

【5】错误处理: 添加一个“error”事件侦听器

app.on('error', (err, ctx) => {
  log.error(err, ctx)
});

【6】next(): 该函数暂停,并将控制传递给定义的下一个中间件

const Koa = require('Koa');  // 引入Koa
const app = new Koa();  // 创建Koa实例,定义Application

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)

五、context (上下文)

Koa 提供一个 Context 对象,表示一次对话的上下文。Context对象将 node 的 HTTP请求(request ) 对象 和 HTTP响应(response )对象封装到单个对象中,通过加工这个对象,就可以控制返回给用户的内容。

【1】Context 具体方法

  1. ctx.req:node的request对象
  2. ctx.res:node的response对象
  3. ctx.request:koa的request对象
  4. ctx.response:koa的response对象
  5. ctx.state:推荐的命名空间,用于通过中间件传递信息和你的前端视图
  6. ctx.app:应用程序实例引用
  7. ctx.cookies.get(name, [options]):获取cookie
  8. ctx.cookies.set(name, value, [options]):设置cookie
  9. ctx.throw([status], [msg], [properties]):抛出异常
  10. ctx.assert(value, [status], [msg], [properties]):抛出错误

六、Request(请求)

Koa Request 对象是在 node 的 原生请求对象之上的抽象,提供了诸多对 HTTP 服务器开发有用的功能。

  1. request.header:请求标头对象,可以设置赋值 (request.header=xxx)

  2. request.headers:请求标头对象,别名为 request.header,可以设置赋值 (request.headers=xxx)

  3. request.method:请求方法,可以设置赋值 (request.method=xxx)

  4. request.length:返回以数字返回请求的 Content-Length,或 undefined

  5. request.url:获取请求 URL,可以设置请求 URL, 对 url 重写有用 (request.url=xxx)

  6. request.originalUrl:获取请求原始URL

  7. request.origin:获取URL的来源,包括 protocol 和 host

  8. request.href:获取完整的请求URL,包括 protocol,host 和 url

  9. request.path:获取请求路径名,可以设置赋值,并在存在时保留查询字符串 (request.path=xxx)

  10. request.querystring:根据 ? 获取原始查询字符串,可以设置原始查询字符串 (request.querystring=xxx)

  11. request.search:使用 ? 获取原始查询字符串,可以设置原始查询字符串 (request.search=xxx)

  12. request.host:存在时获取主机

  13. request.hostname:存在时获取主机名

  14. request.URL:获取 WHATWG 解析的 URL 对象

  15. request.type:获取请求 Content-Type, 不含 "charset" 等参数

  16. request.charset:存在时获取请求字符集,或者 undefined

  17. request.query:获取解析的查询字符串, 当没有查询字符串时,返回一个空对象,可以设置赋值 (request.query=xxx)

  18. request.fresh:检查请求缓存是否"新鲜",也就是内容没有改变。此方法用于 If-None-Match / ETag, 和 If-Modified-Since 和 Last-Modified 之间的缓存协商。 在设置一个或多个这些响应头后应该引用它

  19. request.stale:与 request.fresh 相反

  20. request.protocol:返回请求协议,"https" 或 "http"

  21. request.secure:通过 ctx.protocol == "https" 来检查请求是否通过 TLS 发出

  22. request.ip:请求远程地址

七、Response(响应)

Koa Response对象是在 node 的原生响应对象之上的抽象,提供了诸多对 HTTP 服务器开发有用的功能。

  1. response.header:响应标头对象
  2. response.headers:响应标头对象,别名是 response.header
  3. response.socket:响应套接字
  4. response.status:获取响应状态,默认情况下,response.status 设置为 404 而不是像 node 的 res.statusCode 那样默认为 200,通过数字代码设置响应状态 (response.status=xxx)
  5. response.message:获取响应的状态消息. 默认情况下, response.message 与 response.status 关联,可以将响应的状态消息设置为给定值 (response.message=xxx)
  6. response.length:以数字返回响应的 Content-Length,或者从ctx.body推导出来,或者undefined,可以将响应的 Content-Length 设置为给定值 (response.length=xxx)
  7. response.body:获取响应主体,可以将响应体设置为string 写入、Buffer 写入、Stream 管道、Object || Array JSON-字符串化、null 无内容响应
  8. response.type:获取响应 Content-Type, 不含 "charset" 等参数,可以设置响应 Content-Type 通过 mime 字符串或文件扩展 (response.type=xxx)

【1】 HTTP Response 的类型

Koa 默认的返回类型是text/plain (纯文本的形式),如果想返回其他类型的内容,可以先用ctx.request.accepts判断一下,客户端希望接受什么数据(根据 HTTP Request 的Accept字段),然后使用ctx.response.type指定返回类型。

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

const main = (ctx, next) => {
  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 if (ctx.request.accepts('xml')) {
    ctx.response.type = 'xml';
    ctx.response.body = '<data>Hello World</data>';
  } else {
    ctx.response.type = 'text';
    ctx.response.body = 'Hello World';
  };
}; //直接运行页面中会显示json格式,因为我们没有设置请求头,所以每一种格式都是ok的。   

app.use(main) //app.use(function)用来加载中间件。
app.listen(3000)

八、中间件

【1】介绍

koa 最大的特点就是独特的中间件流程控制,也就是大名鼎鼎的"洋葱模型",我们可以很清晰的看到 一个request请求从外到里一层一层的经过中间件,响应response时从里到外一层一层的经过中间件。就像我们往洋葱插入一根牙签,牙签从外到里经过一层层洋葱皮,到达"葱心",我们拔出来时,牙签从里到外经过一层一层洋葱皮。

【2】案例

基本上,Koa 所有的功能都是通过中间件实现的,每个中间件默认接受两个参数,第一个参数是 Context 对象,第二个参数是next函数。只要调用next函数,就可以把执行权转交给下一个中间件。如果中间件内部没有调用next函数,那么执行权就不会传递下去。下面代码中的

middleware1、middleware2、middleware3 函数就叫做"中间件"(middleware),因为它处在 HTTP Request 和 HTTP Response 中间,用来实现某种中间功能。app.use() 用来加载中间件

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

// 定义三个中间件的方法:middleware1、middleware2、middleware3,next()方法代表执行完当前中间件方法后,继续执行后面的方法
const middleware1 = function async(ctx, next) {
  console.log('这是第一条middleware');
  next();
  console.log('这是第一条next之后的打印')
}
const middleware2 = function async(ctx, next) {
  console.log('这是第二条middleware');
  next();
  console.log('这是第二条next之后的打印')
}
const middleware3 = function async(ctx, next) {
  console.log('这是第三条middleware');
  next();
  console.log('这是第三条next之后的打印')
}

// 使用中间件方法
app.use(middleware1)
app.use(middleware2)
app.use(middleware3)

app.listen(5000)

【3】中间件栈

多个中间件会形成一个栈结构(middle stack),以"先进后出"(first-in-last-out)的顺序执行

  1. app.use()是顺序执行,先引用哪个中间件,哪个中间件的方法就会先执行

  2. 当遇到next()时,Koa就会把当前的中间文交到下一个中间件去进行处理

  3. 如果某个方法中没有定义next(),Koa就会默认把这次请求终止掉,然后返回数据

  4. 如果next()后面有代码,Koa就会等整个应用按照app.use()顺序调用之后,再回来反向执行next()之后的代码,这也就是刚才说到的先进后出。

九、Koa-router(路由)

网站一般都有多个页面,当我们去请求不同api或不同路径的时候,我们要执行不同的方法,返回不同的结果,这个时候,我们就要去借助Koa的中间件Koa-router去处理了

【1】安装Koa-router

 npm install -S koa-router

【2】案例

const Koa = require('Koa');
const Router = require('koa-router');  // 引用koa-router
const app = new Koa();
const router = new Router();

// 定义get请求
// home是我们定义的访问路径:localhost:8000/home
router.get('/home', ctx => {
  // 这个区域是中间件要去处理的上下文方法
  ctx.body = '这是主页'
})

router.get('/detail', ctx => {
    ctx.body = '这是详情页'
})

// app.use(router.routes()) 是把上面定义的路由里面的方法添加到Koa应用中
// allowedMethods方法可以把它看做一个拦截器,可以拦截一些我们应用没有定义的请求,然后返回相应的错误信息

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

app.listen(4000);  // 设置端口号,让Koa应用运行4000端口上;

// 在浏览器访问 localhost:8000/home 输出了"这是主页"
// 在浏览器访问 localhost:8000/detail 输出了"这是详情页"

十、参考链接

koa.bootcss.com/

www.ruanyifeng.com/blog/2017/0…

文章每周持续更新,可以微信搜索「 前端大集锦 」第一时间阅读,回复【视频】【书籍】领取200G视频资料和30本PDF书籍资料

​​