Koa的坑与在express上使用async/await

Author Avatar calidion 发表于 • 2016年11月15日 12:33 • 共 • 861 • 次浏览

背景

javascript异步调用语法上的同步化的完成

注:异步调用语法上的同步化之后将通过异调语同来代替 时间过的很快,随着v8添加对async/await的支持,javascript在语言层面的异调语同过程已经宣告结束了,未来几个星期,这个特性就会出现在nodejs的正式版本上。 从而让javascript语言在整体上已经完成从callback, Promise, generator, async/await的整个演变过程。并且决定了未来主要的编程形式将是以callback与async/await两种调用为主流的调用形式了。

以后大部分的promise都将会被async/await所替换。 只要

async function asyncInvoke() {
...
}

然后执行一下

await asyncInvoke()

那么就能完成一个异步调用了,解决了原来的回调地狱与Promise过于复杂的问题。 可以说是未来一片光明,前途一片大好。 但是好东西一旦出来,常常并不是全都一片叫好的。感觉也是几家欢乐几家愁啊。 今天我们想说的是谁呢?其实就是koa与express.

express vs koa

express作为最成熟的nodejs上的web框架之一,目前仍是用户使用量最高的框架。 koa是一个急先锋,是为让用户更早的体验同步化编程的乐趣而创建的。

其实时至今日koa一直没有能超越express,原因很简单,koa解决的问题跟express没有关系,同时koa还引入了好几个错误。

koa试图解决的问题

koa试图解决的问题实际上是js语言的问题。而不是express的问题。但是koa并没有解决好。 因为原来的作者可能试图直接升级到新的版本。但是因为变动太多,导致阻力太大,所以别起一个轮子,并号称是下一代的框架。 而实际上koa将很多人带进了坑里。 虽然我不是资深的koa开发者,但是我是一个资深的开发者。 下面我说说我发现的几个koa自己挖的坑。

koa的坑

在koa1里使用了this指针,可能是一个最大的坑。

我们知道javascript里this指针是非常容易拖手的。很多使用了

var self = this

这样的代码的库是很容易出现调用风险的。而koa1里竟然明目张胆的推荐使用this.*这种形式。 可以说是非常失败的决策。

异调语同与回调的混搭风

不管是generator还是async/await都是为了避免回调而产生的,但是不管是koa1还是koa2的中间件里,你都能发现next回调函数。 这样显得非常的不伦不类,概念不清楚。

生硬的破坏事件循环

事件循环异调语同是不同的。事件循环是一个等待第三方的过程,处理不处理是不确定的,而异调语同则是等待必须能完成的事件,最多是出个错。所以对于http的请求来说,它是一个事件循环,而不是异调语同。 所以不管是采用generator还是采用async/await都是错误的理解方式。 所以原来的回调模型更适合于http事件的处理。

重造轮子的代价

由于express是一个复杂的生态,所以koa同样也是一个复杂的生态。最重要的是,一个健康的生态不会对人造成困扰,而不健康的生态会对人生成困扰。koa目前来看正处于一个不健康的生态之中。

难说下一代

koa给自己的定位是下一代的Web框架,但是很遗憾,koa的理念上存在严重的错误,很难担当起下一代的担子。并且最近koa社区的issue来看,很多人已经开始意识到koa的问题了。只可惜很多人已经上般了。

koa的其它问题

一个项目的成熟是需要时间的,koa由于过新,通常测试不充分,接口不稳定,遇到问题可能解决起来会非常困难,无形中增加了项目的开发时间,并且有些方案可能解决起来非常麻烦,或者根本没有解决方案。

express的进击

对于express来说, 1、即承继了事件处理模型的直观性 2、又可以利用JS语法的更新直接使用async/await。 3、同时还兼具多年模块积累下来的成熟性与稳定性 所以选择express来配合async/await简直就是完美。 下面我们一起来看一下express如何与async/await配合。

async/await以express的方式

由于不是所有的node版本都支持async/await的,所以最好是使用babel来实现 当然方式非常的简单:

添加async中间件

与添加普通的函数没有任何的不同,只是这样你可以在函数里调用await。

import 'babel-polyfill';    // 这一个包必须添加,否则运行时解析会出错
    var options = {};
    var app = express();
    main.app = app;
    vig.init(app, errors);
    app.use(async function (req, res, next) {
      console.log('async middle ware!');
      next();
    });
    app.listen(options.port || 2048,
      options.host || 'localhost', function() {
        console.log('server running...');
      });

看use函数就可以了。 注意: import 'babel-polyfill'; 必须调用,否则运行会出错。

添加babel命令行

npm install -g babel-cli

添加.babelrc与安装最新版本


# install the cli and this preset

npm install --save-dev babel-preset-latest
# make a .babelrc (config file) with the preset

echo '{ "presets": ["latest"] }' > .babelrc

将代码通过babel编译成es5

npm install -g babel-cli
babel lib/ -d dist/

运行项目:

node dist/index.js
> server running...

测试

如果你使用mocha 测试,需要安装

npm install --save-dev babel-core babel-polyfill

然后执行

mocha --compilers js:babel-core/register,babel-polyfill

即可.

​ 当然如果是一个大项目,建议配合gulp/grunt来构建测试与代码构建体系。

小结

koa本质没有解决express框架的问题,反而引入了很多原来没有的问题,并且在模型本身存在很大的问题。同时利用了极容易出错的this指针,这是很危险的,很容易出现问题的。 而对于express来说,本身模型就与web的response, request模型很匹配,并且原有的中间件模型也非常的成熟,实用,所以当async/await成熟后,将async/await直接在express应用将来带极大的产生率,可以短期内对koa造成绝对的冲击。因为koa这么多年劳动的结果所带优势基本上是不存在的,反而带来了不少不良的设计理念,所以个人不太看到koa的未来。 所以对于被坑过的koa党,欢迎回归express,对于还没有入坑,期待你谨慎的入坑;对于心存疑虑的,请选择理念正宗的express。

最后编辑于 • 2016年11月15日 12:33 •  

你尚未登录,无法进行回复。