返回介绍

koa 中使用 Generator

发布于 2024-03-01 13:04:49 字数 11545 浏览 0 评论 0 收藏 0

koa 是一个 nodejs 开发的 web 框架,所谓 web 框架就是处理 http 请求的。开源的 nodejs 开发的 web 框架最初是 express

我们此前说过,既然是处理 http 请求,是一种网络操作,肯定就会用到异步操作。express 使用的异步操作是传统的callbck,而 koa 用的是我们刚刚讲的Generator(koa v1.x用的是Generator,已经被广泛使用,而 koa v2.x用到了 ES7 中的async-await,不过因为 ES7 没有正式发布,所以 koa v2.x也没有正式发布,不过可以试用)

koa 是由 express 的原班开发人员开发的,比 express 更加简洁易用,因此 koa 是目前最为推荐的 nodejs web 框架。阿里前不久就依赖于 koa 开发了自己的 nodejs web 框架 egg

国内可以通过koa.bootcss.com查阅文档,不过这网站依赖了 Google 的服务,因此如果不科学上网,估计会访问会很慢

提醒:如果你是初学Generator而且从来没有用过 koa ,那么这一节你如果看不懂,没有问题。看不懂就不要强求,可以忽略,继续往下看!

本节演示的代码可参考这里

本节内容概述

  • koa 中如何应用Generator
  • koa 的这种应用机制是如何实现的
  • 接下来...

koa 中如何应用Generator

koa 是一个 web 框架,处理 http 请求,但是这里我们不去管它如何处理 http 请求,而是直接关注它使用Genertor的部分————中间件

例如,我们现在要用 3 个Generator输出12345,我们如下代码这么写。应该能看明白吧?看不明白回炉重造!

let info = ''
function* g1() {
    info += '1'  // 拼接 1
    yield* g2()  // 拼接 234
    info += '5'  // 拼接 5
}
function* g2() {
    info += '2'  // 拼接 2
    yield* g3()  // 拼接 3
    info += '4'  // 拼接 4
}
function* g3() {
    info += '3'  // 拼接 3
}

var g = g1()
g.next()
console.log(info)  // 12345

但是如果用 koa 的 中间件 的思路来做,就需要如下这么写。

app.use(function *(next){
    this.body = '1';
    yield next;
    this.body += '5';
    console.log(this.body);
});
app.use(function *(next){
    this.body += '2';
    yield next;
    this.body += '4';
});
app.use(function *(next){
    this.body += '3';
});

解释几个关键点

  • app.use()中传入的每一个Generator就是一个 中间件,中间件按照传入的顺序排列,顺序不能乱
  • 每个中间件内部,next表示下一个中间件。yield next就是先将程序暂停,先去执行下一个中间件,等next被执行完之后,再回过头来执行当前代码的下一行。因此,koa 的中间件执行顺序是一种洋葱圈模型,不过这里看不懂也没问题
  • 每个中间件内部,this可以共享变量。即第一个中间件改变了this的属性,在第二个中间件中可以看到效果。

koa 的这种应用机制是如何实现的

前方高能————上面介绍 koa 的中间价估计有些新人就开始蒙圈了,不过接下来还有更加有挑战难度的,就是以上这种方式是如何实现的。你就尽量去看,看懂了更好,看不懂也没关系————当然,你完全可以选择跳过本教程直接去看下一篇,这都 OK

加入我们自己实现一个简单的 koa ———— MyKoa ,那么仅需要几十行代码就可以搞定上面的问题。直接写代码,注意看重点部分的注释

class MyKoa extends Object {
    constructor(props) {
        super(props);

        // 存储所有的中间件
        this.middlewares = []
    }

    // 注入中间件
    use (generator) {
        this.middlewares.push(generator)
    }

    // 执行中间件
    listen () {
        this._run()
    }

    _run () {
        const ctx = this
        const middlewares = ctx.middlewares
        co(function* () {
            let prev = null
            let i = middlewares.length
            //从最后一个中间件到第一个中间件的顺序开始遍历
            while (i--) {
                // ctx 作为函数执行时的 this 才能保证多个中间件中数据的共享
                //prev 将前面一个中间件传递给当前中间件,才使得中间件里面的 next 指向下一个中间件
                prev = middlewares[i].call(ctx, prev);
            }
            //执行第一个中间件
            yield prev;
        })
    }
}

最后我们执行代码实验一下效果

var app = new MyKoa();
app.use(function *(next){
    this.body = '1';
    yield next;
    this.body += '5';
    console.log(this.body);  // 12345
});
app.use(function *(next){
    this.body += '2';
    yield next;
    this.body += '4';
});
app.use(function *(next){
    this.body += '3';
});
app.listen();

接下来...

Generator的应用基本讲完,从一开始的基础到后面应用到异步操作,再到本节的高级应用 koa ,算是比较全面了。接下来,我们要再回到最初的起点,探讨Generator的本质,以及它和callback的关系。

还是那句话,搞明白原理,才能用的更加出色!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文