koa

2022-07-05  本文已影响0人  浮若年华_7a56

1.koa是什么?
koa是Express的下一代基于Node.js的web框架,目前有1.x和2.0两个版本。experss是第一代最流行的框架,它对node的http模块进行了封装,但它基于es5的语法,要使用异步代码,只有一个方法:回调。如果异步嵌套层次过多,代码写起来就非常难看,随着新版Node.js开始支持ES6,Express的团队又基于ES6的generator重新编写了下一代web框架koa。
和Express相比,koa 1.0使用generator实现异步,代码看起来像同步的:

var koa = require('koa');
var app = koa();

app.use('/test', function *() {
  yield doReadFile1();
  var data = yield doReadFile2();
  this.body = data;
});

app.listen(3000);

koa2

koa团队并没有止步于koa 1.0,他们非常超前地基于ES7开发了koa2,和koa 1相比,koa2完全使用Promise并配合async来实现异步。

koa2的代码看上去像这样:

app.use(async (ctx, next) => {
await next();
var data = await doReadFile();
ctx.response.type = 'text/plain';
ctx.response.body = data;
});

app.callback()
返回适用于 http.createServer() 方法的回调函数来处理请求。你也可以使用此回调函数将 koa 应用程序挂载到 Connect/Express 应用程序中。

我们可以对ctx操作,并设置返回内容。但是为什么要调用await next()?

原因是koa把很多async函数组成一个处理链,每个async函数都可以做一些自己的事情,然后用await next()来调用下一个async函数。我们把每个async函数称为middleware,这些middleware可以组合起来,完成很多有用的功能。
middleware的顺序很重要,也就是调用app.use()的顺序决定了middleware的顺序。

此外,如果一个middleware没有调用await next(),会怎么办?答案是后续的middleware将不再执行了。
注意ctx对象有一些简写的方法,例如ctx.url相当于ctx.request.url,ctx.type相当于ctx.response.type

koa-router

为了处理URL,我们需要引入koa-router这个middleware,让它负责处理URL映射。
先在package.json中添加依赖项:

"koa-router": "7.0.0"

然后用npm install安装。

接下来,我们修改app.js,使用koa-router来处理URL:

const Koa = require('koa');

// 注意require('koa-router')返回的是函数:
const router = require('koa-router')();

const app = new Koa();

// log request URL:
app.use(async (ctx, next) => {
   console.log(`Process ${ctx.request.method} ${ctx.request.url}...`);
   await next();
});

// add url-route:
router.get('/hello/:name', async (ctx, next) => {
  var name = ctx.params.name;
  ctx.response.body = `<h1>Hello, ${name}!</h1>`;
});

router.get('/', async (ctx, next) => {
  ctx.response.body = '<h1>Index</h1>';
});

// add router middleware:
app.use(router.routes());

app.listen(3000);
console.log('app started at port 3000...');

注意导入koa-router的语句最后的()是函数调用:

const router = require('koa-router')();
相当于:

const fn_router = require('koa-router');
const router = fn_router();

koa-bodyparser

用post请求处理URL时,我们会遇到一个问题:post请求通常会发送一个表单,或者JSON,它作为request的body发送,但无论是Node.js提供的原始request对象,还是koa提供的request对象,都不提供解析request的body的功能!

所以,我们又需要引入另一个middleware来解析原始request请求,然后,把解析后的参数,绑定到ctx.request.body中。

koa-bodyparser就是用来干这个活的。

我们在package.json中添加依赖项:

"koa-bodyparser": "3.2.0"

然后使用npm install安装。

下面,修改app.js,引入koa-bodyparser:

const bodyParser = require('koa-bodyparser');

在合适的位置加上:

app.use(bodyParser());

由于middleware的顺序很重要,这个koa-bodyparser必须在router之前被注册到app对象上。

现在我们就可以处理post请求了。写一个简单的登录表单:

router.get('/', async (ctx, next) => {
  ctx.response.body = `<h1>Index</h1>
    <form action="/signin" method="post">
        <p>Name: <input name="name" value="koa"></p>
        <p>Password: <input name="password" type="password"></p>
        <p><input type="submit" value="Submit"></p>
    </form>`;

});

router.post('/signin', async (ctx, next) => {
  var
    name = ctx.request.body.name || '',
    password = ctx.request.body.password || '';
  console.log(`signin with name: ${name}, password: ${password}`);
  if (name === 'koa' && password === '12345') {
      ctx.response.body = `<h1>Welcome, ${name}!</h1>`;
  } else {
      ctx.response.body = `<h1>Login failed!</h1>
      <p><a href="/">Try again</a></p>`;
  }
});
上一篇 下一篇

猜你喜欢

热点阅读