5

koa第二篇:中间件级联与await next()

 2 years ago
source link: https://xushanxiang.com/2022/03/koa-middleware-cascade-await-next.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

koa第二篇:中间件级联与await next()

作者: xusx 分类: JavaScript,其它 发布时间: 2022-03-27 11:43

koa 把很多 async 函数组成一个处理链,每个async函数都可以做一些自己的事情,然后用 await next() 来调用下一个 async 函数。我们把每个 async 函数称为 middleware (中间件),这些 middleware 可以组合起来,完成很多有用的功能。

下面的 例子 在页面中返回 “Hello World”,然而当请求开始时,请求先经过 x-response-time 和 logging 中间件,并记录中间件执行起始时间。

然后将控制权交给 reponse 中间件。当一个中间件调用next()函数时,函数挂起并控件传递给定义的下一个中间件。

在没有更多的中间件执行下游(downstream)之后,堆栈将退出,并且每个中间件被恢复以执行其上游行为。

After there are no more middleware to execute downstream, the stack will unwind and each middleware is resumed to perform its upstream behaviour.

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

完整例子代码( app.js )如下:

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

// x-response-time 中间件

app.use(async (ctx, next) => {
    console.log('\n开始 x-response-time');
    const start = Date.now();
    await next(); // 调用下一个中间件:logger(等待下一个异步函数返回)
    const ms = Date.now() - start;
    ctx.set('X-Response-Time', `${ms}ms`); // 设置响应头
    console.log('结束 x-response-time\n');
});

// logger 中间件

app.use(async (ctx, next) => {
    console.log('开始 logger');
    const start = Date.now();
    await next(); // 调用下一个中间件:response(等待下一个异步函数返回)
    const ms = Date.now() - start;
    console.log(`\u0020\u0020\u0020\u0020\u0020${ctx.method} ${ctx.url} - ${ms} ms`); // \u0020 为空格
    console.log('结束 logger');
});

// response 中间件

app.use(async ctx => {
    console.log('开始 response');
    ctx.body = 'Hello World';
    console.log('结束 response');
    // 没有更多的中间件执行,堆栈将展开并且每个中间件恢复执行其上游行为
});

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

运行并访问,我们在控制台可以看到:

E:\xushanxiang\nodeproj\koaproj>npm start

> [email protected] start E:\xushanxiang\nodeproj\koaproj
> node app.js

app started at port 3000...

开始 x-response-time
开始 logger
开始 response
结束 response
     GET / - 7 ms
结束 logger
结束 x-response-time


开始 x-response-time
开始 logger
开始 response
结束 response
     GET /favicon.ico - 4 ms
结束 logger
结束 x-response-time

怎么样,执行流程是不是很明了?

如果一个中间件 没有调用 await next(),会怎么办?答案是后续的 middleware 将不再执行了。

这种情况也很常见,例如,一个检测用户权限的 middleware 可以决定是否继续处理请求,还是直接返回403错误:

app.use(async (ctx, next) => {
    if (await checkUserPermission(ctx)) {
        await next();
    } else {
        ctx.response.status = 403;
    }
});

到这里,koa 算是入门了。

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

...
const compose = require('koa-compose');

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

const main = ctx => {
  ctx.response.body = 'Hello World';
};

const middlewares = compose([logger, main]);
app.use(middlewares);
...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK