精华 Koa答疑,你见过这么帅的Node.js代码么?
发布于 1 年前 作者 i5ting 15366 次浏览 最后一次编辑是 7 个月前 来自 分享

Koa答疑,你见过这么帅的Node.js代码么?

为什么要升…

异步代码写烦了,promise也写烦了吧?

koa 1.x通过co,支持generator,你可以yield来写同步代码了

koa 2.x把co移到koa-convert里,把中间件改成的更现代的风格

  • common
  • generatorFunction
  • async/await

express升级koa,成本高吗?

除了koa自身的550行代码和异步流程外(如果熟悉promise/a+规范,成本更低),其他都可以按照express风格一样弄,路由,view,日志,static,生成器、上传等都是一模一样的

  • 熟悉promise/a+规范,通吃
  • 按照express风格一样弄,连express-generator都有对应的koa-generator
  • 中间件机制一样,只是参数有差异

整体来说,我觉得成本比较低。但难在目前koa 2.x的资料非常少。我在写《更了不起的Node 4: 将下一代web框架Koa进行到底》一书的时候,也是非常痛苦的。

下面给出:express和koa比较

https://github.com/koajs/koa/blob/master/docs/koa-vs-express.md

Feature Koa Express Connect
Middleware Kernel
Routing
Templating
Sending Files
JSONP

这是一份很久以前的文档,目前来看也是对的,但是koa的生态已经很好了

Feature Koa Express Connect
Middleware Kernel
Routing ✓ koa-router
Templating ✓ koa-views
Sending Files ✓ koa-send
JSONP ✓ koa-safe-jsonp

该有的基本都有了,于是我仿着express-generator写了koa-generator

技术栈如下

generator是生成器的意思,用于生成项目骨架,express-generator就是一个比较好的例子,虽然比较精简,但结构清晰,足矣满足一帮性需求

鉴于很多人非常熟悉expressjs,我就假定大家也熟悉express-generator

express-generator提供的功能

  • 生成项目骨架
  • 约定目录结构(经典,精简,结构清晰)
  • 支持css预处理器

koa-generator提供的功能

  • 生成项目骨架
  • 约定目录结构(和express-generator的结构一模一样)
  • 支持css预处理器(暂未实行)

那是不是就一样简单了?

如果express还不太熟悉,还是先看express吧,毕竟资料比较多。如果有机会,有人带的话,一定要学Koa的,它是趋势,无论性能、语法、生态,都会有非常明显的优势。

https://cnodejs.org/topic/56650091e7cd33da066d6ee7

sails不能用吗

express加个皮,和rails有点像而已

我对sails和meteor是一个态度,都是特定场景下的快速开发的好东西,就是对程序员要求比较高一点,如果有人能够hold住,其实用了,还是会提高效率的。

我总结了几点sails的缺点

  • 1)sails不活跃
  • 2)orm一堆坑
  • 3)社区很差

如果没有rails背景和很好的express基础的话,没啥太大意义。

对于掌握express的同学. 如何学习koa更快😂😂

参见问题【express升级koa,成本高吗?】

学习更快

  • 按照express的方式玩koa啊,以自己最擅长的经验,学习新东西是最快的
  • koa-generator可以玩玩

这样就可以koa入门了,然后玩一下moa2框架 + moag脚手架,对理解koa的一些好的实践是有好处的。

这些内容都会在《更了不起的Node 4: 将下一代web框架Koa进行到底》一书,等出版了可以买一本哦

没有必要升级koa

天要下雨,娘要嫁人的,随意

但技术栈是发展的,未必不是必要的,哈哈,就好比es6特性一样,以前不敢用,现在遍地都是,是不能不用。Koa亦然。

koa 比 express 好在哪? koa优势是啥?

同问、提升有哪几方面?1,2,3?

以koa 2.x为例吧

  • 性能,比express只强不弱
  • 语义上更清晰,更接近同步,无论是promise还是yield,还是await,都有各种支持
  • 更好利用Node 4.x +版本的es6特性,更加现代

再加一点吧,大家都往哪里使劲,大家还是有感觉的,趋势啊。

比如说性能提升,主要是哪方面的

  • 执行速度:Node 4 比之前版本性能提升,非常大,node 6在模块加载上又有大优化,整体来说越来越强大,执行速度越来越快
  • 内存:越来约省
  • 并发数:越来越高

具体数据还没有,到4的时候基本是翻倍的,之后的数据没严格比较过,抽空测测

在web的框架层面上有什么支持

没啥支持

  • 不捆绑任何中间件
  • 不带有路由

这算小而美哲学的一种体现,模块职责单一,其他的功能其他模块来做就好了。koa算基础模块,所以未来基于koa的框架会有非常非常多的。目前没有特别好的框架,我的moa2也只是起步,哈哈

koa 1都没看,koa 2就来了

其实,koa2比koa多了什么东西或者说优化了什么东西?

核心api基本无变化,主要是中间件变化,去掉co,移到convert里了

看koa-convert https://github.com/koajs/convert

1.x

var koa = require('koa');
var app = koa();
  • 只支持generator写法的中间件
app.use(function *(){
  this.body = 'Hello World';
});

2.x

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

注意new

  • common
app.use((ctx, next) => {
  const start = new Date();
  return next().then(() => {
    const ms = new Date() - start;
    console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
  });
});
  • generatorFunction
app.use(co.wrap(function *(ctx, next) {
  const start = new Date();
  yield next();
  const ms = new Date() - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
}));
  • async/await(Babel required)
app.use(async (ctx, next) => {
  const start = new Date();
  await next();
  const ms = new Date() - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});

这里的中间件差异,可以这样理解,generator里的上下文是this,所以没显式传,而其他的,为了convert方便,以ctx显示传值。

next和express里的next的机制是一样的,就是返回值可以yield或await而已,其实它是promise包裹了而已。

我想知道 用 ES6 写 Koa 怎么调试

之前写过《【视频教程】使用vscode调试koa2-example》

https://cnodejs.org/topic/572209ea35af8a704195f552

里面有讲如何用vscode调试koa的。

es6里使用runkoa也是可以的,不过需要加#!/usr/bin/env node 这个是一定要加的,不然vsc不能识别。

很想知道单线程下,express是如何保证高并发性能的

看node.js基础去吧

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
  • event-driven
  • non-blocking I/O

会不会一个线程崩了项目就黄了?

没尝试的一个问题,算了,还是回答吧

Node.js是但线程的,但一台机器上可以多个实例啊

真正的项目不会只部署一台机器,负载均衡是必须做的

多个机器上部署,每台机器上多个实例(一般是cpu核数)

  • 就算一个实例宕机,还有当前机器上的其他实例,和其他机器
  • 就算实例宕机导致当前机器的实例全部宕机,还有其他机器可以提供服务

如果说,所有实例和所有机器都宕机了呢?这种中彩票的几率还真挺难遇到的。

目前部署Node.js应用,使用pm2这个工具比较好

pm2 在单机上做多核处理

外部多台机器做复杂,所以不会项目黄掉

如果你部署1台1核的服务器,不好意思。。。。一定会黄

pm2挂了呢?

你的负载呢?还有其他机器可以提供服务

好多次直接被运维kill了

那是你监控做的不到位

我一直觉得hapi特别屌

Hapi写rest很顺手

npm自己用的就是hapi

restify也不错的

Node.js世界里有好多框架,喜欢就好,能搞定更好。

koa应该已经原生支持了很多es6特性了吧?

是node支持

6.0除了import几乎都支持了

import可以用这个模块玩, https://github.com/benjamn/reify

另外async/await是es7的stage 3的特性,也没有支持。

所以目前babel是比较流行的,但多少会有性能损耗。

koa2和koa1之间该选koa2还是koa2还是koa2?

现在到底是生产环境用koa2还是koa1,最近正在转战koa,一直有这个困惑?

推荐Koa 2.x版本

  1. 性能比1.x要好
  2. 是以后koa发展重点,1.x的写法会在3.x里干掉
  3. 为以后async/await切换提供学习机会

暂时不用async的原因是什么?

babel的实现效率比较低,见koa、koa2、koa2-async和express的压测性能比较http://17koa.com/koa-benchmark/ ,随着中间件的增多,效率直线下降。

先学着,但不要上产品环境。等Node.js原生支持了就用啊,它也是趋势,绝对好东西。估计10月份就能实现

 Async/await should arrive – behind an ‘experimental’ flag – in Chrome 53, which is scheduled to be released into stable channel on 6 September, so will hopefully arrive (behind a flag) in Node v7, in October.

发现restful设计起名字的时候好费脑子啊😱

刚开始接触nodejs,直接上koa2,行吗?

Koa 2.x资料非常少,如果没有人带或教的话,还是不要上koa 2.

一个东西它再好,也要考虑自身情况的。

《更了不起的Node 4: 将下一代web框架Koa进行到底》一书什么时候出版?

好多人问,可能是国内第一本关于koa的书,签的合同是博文视点出版社

下周去北京,会和编辑商量出版日期的,请大家耐心等待。

看一下Koa 2 帅帅的代码

restful api

/**
 * Auto generate RESTful url routes.
 *
 * URL routes:
 *
 *  GET    /users[/]        => user.list()
 *  GET    /users/new       => user.new()
 *  GET    /users/:id       => user.show()
 *  GET    /users/:id/edit  => user.edit()
 *  POST   /users[/]        => user.create()
 *  PATCH  /users/:id       => user.update()
 *  DELETE /users/:id       => user.destroy()
 *
 */

看起来很爽有木有?

中间件

Koa 2.x最常见的modern中间件

exports.list = (ctx, next) => {
  console.log(ctx.method + ' /users => list, query: ' + JSON.stringify(ctx.query));

  return User.getAllAsync().then(( users)=>{
    return ctx.render('users/index', {
      users : users
    })
  }).catch((err)=>{
      return ctx.api_error(err);
  });
};

只要懂promise/a+规范,就能搞定,所以你以前玩express的经验,还是会非常有用呢~

Koa 2.x中使用generator

exports.list = function *(ctx, next) {
  console.log(ctx.method + ' /students => list, query: ' + JSON.stringify(ctx.query));
  
  let students = yield Student.getAllAsync();
  
  yield ctx.render('students/index', {
    students : students
  })
};

有木有同步的感觉?

let students = yield Student.getAllAsync();

本来从数据库里获取所有学生信息是异步的操作,但是yield把它掰弯成同步的,有木有很爽?

实际上,它也是co包过的,这样更便于处理err

router.get('/list', (ctx, next) => {
  return co.wrap($.list)(ctx, next).catch(err => {
    return ctx.api_error(err);
  })
}); 

代码就这么精简

Koa 2.x中使用async/await

exports.list = async (ctx, next) => {
  console.log(ctx.method + ' /students => list, query: ' + JSON.stringify(ctx.query));
  try {
    let students = await Student.getAllAsync();
  
    await ctx.render('students/index', {
      students : students
    })
  } catch (err) {
    return ctx.api_error(err);
  }
};

它和generator其实没有太多区别,一样简单、命令,一通百通。

性感的ava测试

// *  GET    /users[/]        => user.list()
test('GET /' + model, function * (t) {
  var res = yield superkoa('../../app.js')
    .get('/' + model)

  t.is(200, res.status)
  t.regex(res.text, /table/g)
})

测试也成了同步的感觉,有木有爽爽哒?

来个更复杂的原子性测试

// *  GET    /users/:id       => user.show()
test('GET /' + model + '/:id show', function * (t) {
  var res1 = yield superkoa('../../app.js')
    .post('/api/' + model)
    .send(mockUser)
    .set('Accept', 'application/json')
    .expect('Content-Type', /json/)

  user = res1.body.user

  var res = yield superkoa('../../app.js')
    .get('/' + model + '/' + user._id)

  t.is(200, res.status)
  t.regex(res.text, /Edit/)
})

想要测试展示,就要先创建,每一步都是同步的,是不是代码逻辑看起来更清楚?

你也想写这样帅帅的代码么?

全文完

欢迎关注我的公众号【node全栈】

node全栈.png

联系我,更多交流

xiaoweiquan.jpeg

80 回复

速度与激情@i5ting 👍

这课程大纲看起来很不错啊

满满地情怀

北新桥科技寺 T1 会议室 ~

2.pic.jpg

详情&报名 微信扫一扫

<img src="//dn-cnode.qbox.me/FtzOmDJ13Tm8n7jNFPaTVNsjQGZG" width=“160” />

文章的不少观点我不敢苟同。

koa作为一种尝试,个人认为是非常有价值的。 但是express作为一种更加直接的调用方式,对于很多人来讲会更加容易接受。

封装有时候会简化流程,但是有时候也会限制人的思考。 同时会导致对需求的限制,甚至无法满足需求,这个问题在面向对象语言里是很普遍的。 所以并非封装了,简化了就是好的,有时候因为封装会导致整个体系重新来过也是有的。

从1.x =》 2.x 的变化还是挺大的,这也是框架与程序演进所不可避免的。 但是同样说明这种框架潜在的风险,不稳定。 co作为一个临时性的解决方案,在语言层面都不是一种讲究的方案。 async/await比较终极,但是express不也可以用吗? 完全跟koa与express本身无关好吗?

还有ctx这种东西是不是好,还需要时间的检验。 至少我不认为切到koa就是一个明智之举。

关于sails的看法,个人认为也是有问题的。 个人认为sails的orm是目前nodejs体系里最实用,最完备的,最节约时间的。如果不是,那也得给出来一个可以与之相抗衡的吧? 但是目前好象没有看到对应的ORM。 koa应该跟ORM没有关系吧?为什么在推荐KOA的时候需要黑一下sails的orm?

sails框架是目前快速原型化框架里最完善的,最全面的框架之一。 任何一个框架都会存在问题,sails框架的问题在于模块化还没有拆分出来。自定义能力相对比较弱。 还有就是代码灵活性较差。 但是koa怎么跟sails比呢?完全不是一个目的的东西。 一个是基础框架,一个是应用型框架,立足于快速原型化的。 如果我们比较的时候连领域都弄错了,比较的意义是什么? 让自行车与卡车比的意义是什么? 如果有一天sails可以支持koa为基础的web框架,你又会作何比较?

至于社区,我看gitter上有很多人提问,活跃度并不比这个论坛差多少,issue也很多。 相比于很多框架还是要活跃很多的,至少我并没有看出来活跃度低的情况。

本人的一个态度,我认为推广一个东西不要总想着贬低别的东西。 如果没有理性的分析,很多时候人们的决定是错误的。 好东西大家会比较,足够好的东西不需要去贬低别人的东西。 并且选择是一种自由,并不是因为你好就必须要用的。 PHP,JAVA, Python也没有因为Nodejs的出现而倒掉。 最近刚好经历了bower vs npm之战,也同样看到了一些国外一些极端分子的疯狂。

如果koa足够好,就给几个大站的案例说明如何应用的,说明各种坑都已经趟过了。 这样就足够让人信服了。不需要去贬低别的框架。

个人比较支持通过数据与案例进行客观的比较。 最重要的是不要总想着取代谁,做好自己不行吗? 难道我们不能允许两个优秀的东西同时存在吗?

如果要比较语言,目前最上路的dialect,ES6 ES7都还是dialect,应该还是TypeScript,类型还是很有用,虽然地球人早知道这个。

https://www.delivoper.com/t/typescript/42

expressJS真有这么难学吗?

Auto generate RESTful url routes. 这个很难么? loopback分分钟搞定,而且就是一点点代码,还支持可视化添加

@calidion 喜欢用sails.js的话推荐试试Strapi http://strapi.io/ 你说的问题很多都已在其中解决。我以前用sails比较多,也写过几个orm数据库的adapter,不过关于orm这块的确写的很烂的,执行效率非常低,我仔细研究过sails-mongo和sails-mysql代码,都不怎么样。现在是比较倾向于的技术栈koa 2 + webpack + react + redux + graphql + koa-graphql + react-router + immutablejs + react-redux + mongoose 另外在考虑是否有必要上relay,据说relay的实时subscription马上要出来了,出来以后react就差不多可以做类似于meteor那种形式的实时的app了

@calidion 看不懂文字么?

sails不能用吗

express加个皮,和rails有点像而已

我对sails和meteor是一个态度,都是特定场景下的快速开发的好东西,就是对程序员要求比较高一点,如果有人能够hold住,其实用了,还是会提高效率的。

我总结了几点sails的缺点

1)sails不活跃
2)orm一堆坑
3)社区很差
如果没有rails背景和很好的express基础的话,没啥太大意义。

我拿koa和sails比了么?

你能搞定sails,你牛逼,但很多人搞不定,所以一直不推荐新人直接使用sails、meteor这样的东西,我并没有说他们不好,只要团队有人能hold住,能在源码级别进行定制,随便用啊

@calidion

co作为一个临时性的解决方案,在语言层面都不是一种讲究的方案。
async/await比较终极,但是express不也可以用吗?
完全跟koa与express本身无关好吗?

我不认为你在express项目里用这些东西,你可以自己说说看

另外 @pana 写过一个比较不错的小项目 https://github.com/Pana/wga

Wrapper for generator and async/await to enable them use in Express or restify

囿于express的中间件机制和koa中间件机制不同,无论怎么适配,还是会比较别扭的,如果同时会2样,对于一些人来说,还不如只会一样呢,当然能力特别强的除外

@calidion

如果koa足够好,就给几个大站的案例说明如何应用的,说明各种坑都已经趟过了。
这样就足够让人信服了。不需要去贬低别的框架。

koa 1.x在cnpm里应用了,也还算不错吧

koa 2.x已知的广发银行

但目前2.x没正式发布,所以能爆料还不很多

看一个框架或模块好不好,1)是测试,koa 1和2的测试覆盖率都是100% 2)是benchmark性能,我测试的结果是koa比express率高

@andyhu strapi看起来不错哦。你推荐的栈好潮啊,Node全栈,哈哈

@i5ting

是我不懂文字,还是你在玩弄文字?

你为什么总是替别人假设? 你认为的都是对的?

这个世界需要创新,但是同样也需要多样性。

侨车出来后,自行车就必须退出? 我总怀疑你的思维方式是不是有问题。

你接受了koa必须所有人都接受? koa对express的替代性我为什么一点也看不出来呢? 一旦async/await成熟express分分钟就可以切换过来。

关于覆盖率的问题,搞得好象express不是100%似的?

@calidion 你可以看看全文,有没有说koa出了,就必须不能用express(退出),我没有这个意思吧?

亲,科普Koa,也是错么?

@andyhu +1 咱俩的技术栈观点一致…另外vue也不错, 可以尝试

@i5ting

科普,推广都没有问题。

但不要随意摸黑别的框架,特别是完全没有意义的黑。

generator, co, promise那个不能在express里使用?

科普的前提是你自己得理解对吧。

@calidion 我有说不能在express里用么?请举例

囿于express的中间件机制和koa中间件机制不同,无论怎么适配,还是会比较别扭的,如果同时会2样,对于一些人来说,还不如只会一样呢,当然能力特别强的除外

这里只是说,用在express不会比koa里爽而已,express里用generator回稍稍别扭,另外我也给出了pana的模块

@i5ting

看你写的比express好在那里,既然promise, yield不是express与koa的差别。那么这样写是不是有误导的效果呢? 语义本来就不是框架的特点。 然后如果明天出来个soa框架,是不是所有人马上退出koa? 并且现在用的劲最多的也是express啊,按你的意思显然应该支持express. 宣传koa没有找到点。

以koa 2.x为例吧

性能,比express只强不弱
语义上更清晰,更接近同步,无论是promise还是yield,还是await,都有各种支持
更好利用Node 4.x +版本的es6特性,更加现代
再加一点吧,大家都往哪里使劲,大家还是有感觉的,趋势啊。

@calidion 出了好的,我能搞定我就迁移啊

比如k1没有k2好,那我自然就会考虑k2,趋利避害不是人的本性么?

可是,你之前的项目又不是不要了啊,维护,升级,重构,放弃,这就随你了。是不是?

express是目前最多的,最稳定,资料也是最全的,无出其右。官方也说了,Koa是下一代的web框架,它有它的优势,我说的那几点优势,没错吧?

generator是 es 6特性,node从4开始就默认支持了,这是趋势,还是要适当使用的

koa文档手,对于新手来是一天沟 From Noder

非常想去但实在是分身乏术呀,期待新书,肯定支持一本

不太理解为啥这种广告文章需要置顶,敢问 @i5ting 你把 cnode 当做你自己的后花园了么?发什么文章都置顶

@lcjnil 我置顶的。

一般来说,都是我在加精和置顶。

夹带广告不代表这篇文章不够价值啊。

@alsotang

敢问置顶,加精的标准是什么? 有严格的执行标准,还是说完全根据个人心情?

@calidion 没有标准,但肯定也不是看心情的。

写文章不容易,有争议也不奇怪。

这篇文章我觉得是输出了知识的,也提供了不少相关参考资料的介绍和链接。虽然作者在文中有他自己的倾向性,可能说了一些比较主观的看法,但大体上,我觉得本文对社区是有帮助的。

@alsotang

当然加精,置顶还是你个人的事情,本身国内也没有真正意义上的社区。

但是个人认为文章的倾向性过强了。

koa并不能马上取代express. 也不见得就是下一代的框架。

自封下一代的框架太多了。

跟上一次攻击某一家公司是完全一样模式,属于洗脑式传播。

并且内容多有错误,有些错误我已经在前面指出来了。 有很多误导性的内容。

至少看完会让所有人觉得好象express无法使用promise, generator, async/await.

那家公司的情况我现在不是很清楚,但是我认为即使是程序员,最好也能够掌握一定的政治正确。

令我印象深刻的是seajs当年的推广手段,跟这个也是一样的。

相信被seajs坑的人也不少,当年seajs的人还跟我有过一场论战。

其实我并没有反对过seajs的发展,但是同在这里一样,我反对洗脑式的推广一个产品, 并且将别的产品说的好像就没有生存机会了一样。

seajs的到目前还没有requirejs发展的好。

koa目前也没有express的用户广。

也许等koa快追上express的时候, 某个第三方框架会突然出现。

koa也不一定会有机会超过express.

综上,我认为宣传技术本身是应该提倡的,但是建立在错误的认知之上,并且通过抵毁式推广方式可能反尔让别人觉得不爽。 你可以宣传很多优点,并且做比较,但是千万别随便的诋毁别的框架,搞的别的框架马上就要倒掉似的。

非常反感类似的手法进行推广。

我也不反对抱团,但是抱团不要抱的太low.

@calidion 下次如果有类似介绍 express 的文章,或者 sails 的文章,能向 @i5ting 一样整理那么多内容,我也一样置顶。

我相信错误的认知对于 @i5ting 来说是不存在的,只是他有自己的倾向性而已。对于一个最近一直做 koa 相关事情的人来说,他的这种倾向性我能理解。

抱团这事,你不提我真没想过。。。他一个男的我跟他抱一起干嘛。。。

@calidion 由于他的倾向性导致文中出现了一些不太客观的表述,这一点我刚看的时候就体会到了。

不过每个人在积极推广或者宣传一样东西的话,不可避免都是带有倾向性的。要是你让作者啰啰嗦嗦写一大堆中立的表述,不能吹捧自己喜欢的东西。。这就很阻碍写文章的积极性。

而且 express 和 koa 在我看上,是技术口味问题,有倾向性可以忍。

@alsotang

我完全没有反对个人可以表达对koa的喜好。 并且我也是认同事物是可以比较的,可以存在某些指标的优势的。 但是我不能接受表达喜好的时候贬低别的东西。

这种类似的事情发生过太多 nosql vs sql, seajs vs requirejs

都是以取代的姿势来势凶凶,结果呢?

由于nosql的错误宣传造成的不良影响至今还在。 很多人根本没有搞懂差别就否定了sql.

我希望在宣传koa的时候不至于这那么low.

我对倾向性是理解的,但是如果出现严重的误导,我如果还没有被封号,我一定会出来说几句。

包括宣传前后端分离的人,估计说前后端分离的人自己都没有搞清楚什么是前后端。

同时我也不会反对以更好的文采来宣传,但是我不认为好的文采与贬低别的成果之间有直接的相关性。

我在意是因为我认为有些东西是确定的,而有些东西是可选择的。

koa与express就是一个选择的问题。

@calidion 说的好,难有理性的思考,讲一个技术就差立个旗杆了。是不是加精置顶,其实也就是这个社区本身的价值。呵呵。

From Noder

@SiriusGuo 兄弟,咱就事儿论事儿好不好,不要把唐少扯进来,更不要往社区上抹黑。

如果你们认为koa哪里不好,或者怎么样,我们针对这个来辩论,是有意义的。哪怕我辩不过你们,至少我还能涨涨知识。你们这所谓的理性思考,能不能不歪楼?

毫无疑问的是,未来很长一段时间我都会科普Koa,难免让你们不爽,我觉得我们把这东西讨论透了才是最重要的,好,我们一起推广,不好,我也会绝了这个念想,对事不对人,好不?

@calidion untitled1.png

untitled2.png

图中红框部分在你看来,也是严重的误导、以取代的姿势来势汹汹吗?一个是下一代框架,一个是终极流程控制方案

作為國內接觸 co/koa 比較早的人之一,我在兩年多以前就已經開始使用 Koa 了。不過在我看來 Koa 依然不是目前我所希望看到的“終極”形態,依然存在不足。看到一個東西好處和優勢的同時,也要更加了解它的缺點,這貌似在我看過 @i5ting 這麼多關於 Koa 的文章中並沒有得到體現。

  1. Koa 的設計原理決定了它在同樣的條件下是絕對優於 Express 的,無論在開發體驗和性能上;
  2. 但同樣也是 Koa 的設計原理讓我所能預見到的它在達到某一程度的并發量的時候,所會發生的 IO 瓶頸要如何規避(當然這對於 Express 來說同樣存在),不知 @i5ting 是否有注意到?
  3. @calidion sails 的歷史不亞於 Koa,至於其中有什麼坑,因為本人並沒有很詳細地去了解所以我並沒有資格評價。但是至於社區如何,我覺得 Koa 也並不好到哪裡去,這是事實;

任何人都有擁有自身傾向性的權利,當然也有將這個傾向性向別人傳播的權利。但顯然,過於嚴重的技術傾向性對於一個優秀的工程師來說自然不是什麼好品質,你們說是不是?

@iwillwen 我发现我还是对于技术比较感兴趣。。。

io瓶颈那块可以再描述一下吗?

關於 Koa 的設計原理,我在剛開始接觸 Koa 的時候就已經寫過文章來講解了。其中我以 Go 語言標準庫中的 HTTP 庫作為基準與 Koa 作對比,這裡我不想再累贅。 [http://lifemap.in/koa-co-and-coroutine/](http://lifemap.in/koa-co-and-coroutine)

  1. Go 的真·协程让每一次请求之后的所有逻辑代码(包括请求处理、数据操作和响应等等)都以一个真·协程来作为容器来进行响应;
  2. 而 Koa 中则以“协程”来作为每一次请求中逻辑代码的运行容器,可以,这很清真。但是为了让 JavaScript 得到“同步代码”这个 buff,需要让所有的异步操作(硬盘 IO、网络请求等等)都回到 JavaScript 主线程(只有一个)中进行,相当于让真正堵塞请求的东西都扔回主线程去。如果这个部分没有很好地得到处理,便会出现 IO 瓶颈。当然,这在 express 中就是所有的东西都在主线程中。

楼上竟然能有这么多争论话题,其实没必要啊

  1. 喜欢sails.js的但是觉得坑很多的强烈推荐Strapi,基本能兼容sails.js,在sails里写的代码拿到这里基本可以直接用。作者是sails的维护者之一,而且sails的大多数弊端在这个项目里都有完善,自带admin后台 Strapi http://strapi.io/
  2. 不喜欢sails.js的,推荐这个 https://github.com/kriasoft/react-starter-kit 比较灵活可以自己配置,想用koa的话也可以自己替换,支持isomorphic渲染,速度挺快。就连css可选用比较有意思的postcss+precss,速度比sass,less快很多,还支持更多有意思的语法
  3. 关于sails的orm,如果不介意执行效率低,占用内存大,有时候有点bug的话可以一用,毕竟是node orm里支持数据库种类最多的,不推荐在性能要求很高的网站上使用,看下sails-mongo源码自知

@iwillwen

这恐怕不是是IO瓶颈,而是计算瓶颈。在计算能力一定的情况下(go可以多线程利用CPU,nodejs可以多进程利用CPU),计算瓶颈其实跟单线程还是多线程没多大关系。go可能看起来要好点是因为编译型语言的优势。

nodejs现在最大的问题是类协程实现得比较丑陋,跟go,lua等语言的协程比,编程模型上还是太复杂。

local tcp = require('tcp')
local ERRNO = require('errno')
local send = require('./pool')

local function onconnect(socket)
  local data, err
  while true do
    data, err = socket:read()
    if err < 0 then
      print('front read error: ' .. ERRNO.parse(err))
      return
    end

	-- 这里与后端服务器通信,看起来是同步的,其实是异步的,业务层面的程序员根本不用关心这个操作是同步的还是异步的,当然知道操作的代价最好,这里不需要任何包装和转换,很自然而然的就将异步回调同步化。原理上就是利用lua的协程,在c层将回调异步转化为lua层的形式同步,实质异步。
    data, err = send(data)
    --print(err)
    if err < 0 then
      print('front send error: ' .. ERRNO.parse(err))
      return
    end

    local msg = {
        'HTTP/1.1 200 OK\r\n',
        'Server: LINKS\r\n',
        'Content-Type: text/plain;charset=utf-8\r\n',
        --'Connection: close\r\n',
        'Content-Length: ' .. #data .. '\r\n',
        '\r\n',
        data
    } 
    bytes, err = socket:write(msg)
    if err < 0 then
      print('front write error: ' .. ERRNO.parse(err))
      return
    end
  end
end

local options = {
  reuseport = true
}

local server, err = tcp.createServer(8080, onconnect, options)

我知道的是express用的时候没有遇到什么瓶颈,利用架构平衡都干掉了,所以koa在一样的条件下,并发更好(一点点),那么它和express的瓶颈应该是类似的

@coordcn @iwillwen 就喜欢你们这样较真的人,我其实不是特别懂,你们继续聊,持续关注

@i5ting

桑总的观点是正确的,但我还是要说:::装逼和卖萌都是可耻的。。。

你就直接说计算能力不够加机器,非得用什么架构平衡这么高大上的词汇。

express =》koa =》形式同步,编程模型上的进化对性能影响其实是微乎其微的,但对编程效率的提升是非常大的。

express和koa的选择的关键问题不在于那么一点性能,而是团队对新编程模型的适应性。

@andyhu

多讨论是好的。

本人也是曾经想尝试koa,但是看完generator我就决定不要使用koa了。

对于这种语法接受无能。

我对语法也是非常有洁癖的,直到async/await出来,我才觉得这个方案可以了。

我早就感觉到了koa潜在的风险,所以没有跟进。

对于ctx这种封装,也是我不想跟进koa的原因。

strapi.io 看上去不错。

很多时候性能并不是最主要的。

所以不是很喜欢唯性能论。

@coordcn 你后面说的很对,“express和koa的选择的关键问题不在于那么一点性能,而是团队对新编程模型的适应性”,

你就直接说计算能力不够加机器,非得用什么架构平衡这么高大上的词汇。

这个说的是有问题的,加机器是最差的办法,首先确定瓶颈在哪里,然后根据场景去觉得解决方案。举个例子,一个耗时计算的任务,区分可变与不可变,区分必须同步和可以异步,为什么一定要放在当前代码里呢?用mq能否解决?如果都解决不了,是不是可以考虑用其他语言重写这部分?

@calidion 哈哈,strapi是基于koa 1.x的

对于async/await和ctx这种封装,我觉得你没有真正理解koa 2.x

@coordcn 说的很对,“express和koa的选择的关键问题不在于那么一点性能,而是团队对新编程模型的适应性”,

@i5ting

是的,加机器之前肯定先要弄清楚瓶颈到底在哪里,加机器肯定是靠后的选项。烂代码,烂架构,加机器也白搭。

说个题外话,人比机器贵,如果代码,架构没大问题,出现瓶颈,加机器的优先级应高于加人。

@coordcn 比uber的地理位置服务用go写,我觉得他们比较闲了。go的人的成本更高一些。哎,都是不计成本的玩啊

@i5ting

strapi吸收了sails。 跟是不是基于koa没有太多关系。

我一样不太喜欢ES6,你也可以认为我不理解ES6。

自从ES6以后,我就有打算换到别的语言的冲动。

koa2我需要去理解他吗?

一个不喜欢的人你还有必要主动去接近他?

我不知道你为什么可以如此怪异的思维。

何况我也没有说过我对koa有多了解,我只是天然的不喜欢这种框架。

但是我也没有反对过koa框架的发展。

上面几位说的都挺好的, 我现在业余写的项目是express+sequelize,开发效率高,跑的也挺好,一个人能搞定一个后台开发,也不考虑换什么koa之类的。 @calidion orm上,我觉得sequelize比waterline好用,sails也研究过,感觉没express灵活,难控制,所以放弃了,但sails我觉得真心挺好,还买了他们网站推荐的书,以后可能会再用

另外,真心讨厌做广告的,这是技术论坛,不是给广告发布用的,就好像微信群里、朋友圈里刷代购的一样,希望@alsotang 禁止吧,还我们一片净土,谢谢

@simdm 人家写这篇文章至少写个一天吧?楼上一个说不喜欢有倾向性,一个说不喜欢看到广告。大家都多点理解。

@alsotang 写一天也是广告贴,在技术论坛里,真的非常讨厌这种有功利性的技术倾向性文章。 当然了,言论自由,但至少请以后不要在置顶了,多谢

没看出哪儿帅了,至少没比express帅 express和babel谈笑风生,不知高到哪里去了

@rockdragon 求分享一下

@simdm 我其实不太信你不用koa的,so,你也可以写点别的有技术含量的,本来就是一个技术分享,何苦呢?线上视频比线下赚钱的多,我为啥要费力不讨好呢?

我把里面的广告部分去掉了

@i5ting ES6还没掌握,所以koa不想去学,何况现在express用的挺好。粗略看了一下koa,对于使用者来说,感觉就是express的es6版本,我觉得express都能自学好了,koa自学起来也不难吧。

我文笔太差,从来不写文章,而且技术也挺烂的。。。

技术分享欢迎,广告就算了

@i5ting 请问 koa 2 怎么使用 session

@i5ting 之前陆陆续续有学点node,但由于工作需要精力一直放在react全家桶这块。最近看了很多桑大大发表的东西,赞一个先。跟着桑大大的脚步学习,很期待《更了不起的Node 4: 将下一代web框架Koa进行到底》

mark。新人用过再说,一个社区没有这样的用心写的文章,怎么让想学的人找到尝试的方向。对于node,不断尝试才会学的更快。既然是开放论坛,欢迎分享各种观点和不同意见。但是只打嘴炮,对大多数node爱好者毫无实质益处的,就不要影响技术交流了。 自豪地采用 CNodeJS ionic

支持桑大的分享

感谢lz,我之前印象中node的框架都比较底层,就看哪个框架先上了async/await了

洋葱模型 的应用场景 接触的东西不多, 除了 demo 里的 那个计算时间 的功能外, 还什么其他应用场景吗? 一般不是 response 之后就没有什么操作了吗?

@ConanXie 我的demo

require('app-module-path').addPath(__dirname)
require('colors')

// const _ = require('lodash')
const Koa = require('koa')
const bodyParser = require('koa-bodyparser')
const server = require('koa-static')
const session = require('koa-generic-session')
const redisStore = require('koa-redis')
const flash = require('koa-flash')

const app = new Koa()
// ...
app.keys = ['uinz']
app.use(bodyParser())
app.use(session({ store: redisStore() }))
app.use(flash({ key: 'flash' }))
// ...

配合 redis, 也是摸索阶段 看到不好的代码欢迎告诉我.

分享是支持的,讨论也是支持的,相互攻击就不太喜欢,好与坏看实践的结果吧。我想 @i5ting 肯定也是实践之后才有如此经验之谈的。 @i5ting 在这发 KOA 的文章完全不感到意外,6月份开始他的朋友圈发的基本都是KOA 。。。。。。誒

@iwillwen 这个地址404了http://lifemap.in/koa-co-and-coroutine,另外你不是大陆人吗,为何用繁体字,看得有点累

@Hi-Rube 求pk koa,哈哈

@yinzSE 没有理解生命周期这样hook的好处,response 之后就end了,肯定没啥操作的。可是你不在那里response可以么?

看评论收货良多。。不过某几位的观点不敢认同。。说白了就是我不喜欢koa不用koa所以你就不能吹koa,我不喜欢广告你就不能发广告。。。

没用过express,去年底开始从java转向用nodejs开发,直接就上手了koa,看到koa2就结合babel用2了,结合es6,代码优雅看着就爽,用哪些中间件就安装哪些中间件,感觉整个项目很可控。

	const router = require('koa-router')()
	const userService = require('../services/user')
	  
	router.post('/login', async ctx => ctx.body = await userService.login(ctx.request.body.name, ctx.request.body.pwd))
	router.get('/index', async ctx => await ctx.render('index'))
	
	module.exports = router

express给我感觉spring这种全栈框架,个人不太喜欢

来自酷炫的 CNodeMD

我去 好文 评论更精彩 必须马

https://github.com/moajs/moa2 一个功能足够用的小的基于koa2的封装

目前公司用Koa 1.x + sequelize + mongoose, 以前从express 4.x迁过来的。新的版本没了解过,但是代码写得比以前爽多了~

为啥2.x要多出个ctx?

@jonathanong

这样变化的最主要的原因是,在你写koa apps 时使用async箭头函数的时候:

app.use(async (ctx, next) => {
  await next()
})

这种情况下,使用this是万万不可能的。

因为 Arrow Function是 Lexical scoping(定义时绑定), this指向定义Arrow Function时外围, 而不是运行时的对象。

引用koa的差异

1.x

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

2.x

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

源码

1.x

/**
 * Application prototype.
 */

var app = Application.prototype;

/**
 * Expose `Application`.
 */

module.exports = Application;

/**
 * Initialize a new `Application`.
 *
 * @api public
 */

function Application() {
  if (!(this instanceof Application)) return new Application;
  this.env = process.env.NODE_ENV || 'development';
  this.subdomainOffset = 2;
  this.middleware = [];
  this.proxy = false;
  this.context = Object.create(context);
  this.request = Object.create(request);
  this.response = Object.create(response);
}

2.x


/**
 * Expose `Application` class.
 * Inherits from `Emitter.prototype`.
 */

module.exports = class Application extends Emitter {

  /**
   * Initialize a new `Application`.
   *
   * @api public
   */

  constructor() {
    super();

    this.proxy = false;
    this.middleware = [];
    this.subdomainOffset = 2;
    this.env = process.env.NODE_ENV || 'development';
    this.context = Object.create(context);
    this.request = Object.create(request);
    this.response = Object.create(response);
  }
}

很明显,1.x是函数,而2.x是类,需要new来实例化。

整个Koa2.x里只有application做了类化,其他的还是保持之前的风格,大概还没有到必须修改的时候吧。

回到顶部