本站从express转换到koa框架

作者:杨润炜
日期:2016/4/20 09:43

一开始接触express开发,使用异步的流程来写后端逻辑,总感觉别扭,虽然经过一段时间的开发,慢慢习惯了这些模式,但到后来看到koa中的代码,还是被吸引过去了,js中居然可以用同步的模式来写逻辑,这真是太新鲜了,哈哈。所以便尝试着将本站的框架转到koa来。下面我来说说重构中发现两者的一些差异吧。

从function到generator

express使用的都是function,即一般函数,而koa经常使用的是generator这种特殊的函数,正是因为它,我们才可以写同步的代码喔。generator里可以使用yield,可以使用next方法来逐个调用yield,并且可以通过返回的值来获取状态和操作的数据。但generator不能像普通函数那样加个括号就自动执行,所以koa框架里内置了co这个工具来自动执行generator。
另外需要强调的是yield语句,它可以让我们在generator里调用其它的generator,这使得我们可以封闭我们的控制器。在实际开发中发现,如果被调用的generator里只有一个yield,也可以通过yield直接调用它,而不需要yield

指定静态资源

express版

  1. var express = require('express');
  2. var app = express();
  3. app.use(/^\/blog\/\d+/, express.static('d:/static/blog-portal-static'));

koa版

  1. var Koa = require('koa');
  2. var app = new Koa();
  3. var router = new Router();
  4. var send = require('koa-send');
  5. router.get(/^\/blog\/\d+/, function *() {
  6. this.path = this.path.replace(/^\/blog\/\d+/, '');
  7. yield send(this, this.path, { root: 'd:/static/blog-portal-static' });
  8. });
  9. app.use(router.routes());

因为koa里没有像express里的static内置中间件,所以得自己去处理路由和返回指定静态文件。

判断是否为ajax请求

express

  1. var express = require('express');
  2. var app = express();
  3. app.get('/', function (req, res) {
  4. if (req.xhr) {
  5. console.log('ajax请求');
  6. }
  7. });

koa

  1. var Koa = require('koa');
  2. var app = new Koa();
  3. var router = new Router();
  4. router.get(/^\/blog\/\d+/, function *() {
  5. if (this.headers['x-requested-with']&&this.headers['x-requested-with'].toLowerCase() == 'xmlhttprequest') {
  6. console.log('ajax请求');
  7. }
  8. });

因为koa的this.req里没有xhr这个属性,所以得根据header来判断。这里需要注意的,如果前端用到的框架,比如angularjs,内置的http模块没有x-requested-with,那就得自个儿给htpp请求加这个header值了。

错误监听及捕获错误

express错误的监听

  1. // 500 server error
  2. app.use(function(err, req, res, next){
  3. console.error(req.url, err);
  4. if (req.xhr) {
  5. res.status(500).send('server error');
  6. } else {
  7. // 返回500页面
  8. }
  9. });
  10. //404 NOT FOUND
  11. app.use(function(req, res, next){
  12. if(req.xhr) {//异步
  13. res.send('404 NOT FOUND');
  14. } else {
  15. // 返回404页面
  16. //res.redirect(301, '/err/404.html');
  17. }
  18. });

koa

  1. // 监听404
  2. app.use(function *() {
  3. if (this.headers['x-requested-with']&&this.headers['x-requested-with'].toLowerCase() == 'xmlhttprequest') {
  4. // 异步请求
  5. this.response.body = '404 NOT FOUND';
  6. } else {
  7. this.redirect('/err/404.html');
  8. }
  9. });
  10. // 监听错误
  11. app.on('error', function(err, ctx){
  12. logger.error('server error', ctx.url, err);
  13. ctx.status = 500;
  14. if(ctx.headers['x-requested-with']&&ctx.headers['x-requested-with'].toLowerCase() == 'xmlhttprequest'){//异步
  15. return ctx.res.end('Server Error');
  16. }
  17. //同步请求
  18. ctx.redirect('/err/500.html');
  19. return ctx.res.end();
  20. });

koa监听错误后,会默认返回“Internal Server Error”,而且express没有。这些监听都需要放在应用路由的最后。

执行自定义的函数

express

  1. var fn = function () {
  2. console.log(123);
  3. }
  4. fn();

koa

  1. var co = require('co');
  2. var fn = function () {
  3. console.log(123);
  4. }
  5. var gn = function *() {
  6. console.log(123);
  7. }
  8. fn();
  9. co(gu);

koa里可以用generator函数,但它的执行也可以自动执行器,比如co。

‘use strict’;

koa的开发中,一般会在js文件第一行写上下面这行代码:

  1. 'use strict';

这样可以保证es6的特性可以被我们使用。

co

koa框架是用co来作为generator自动执行器,所以我们可以在generator里使用co的一些特性。
co支持数组、对象、promise返回等多种特性。

1.数组并行执行
  1. co(function *() {
  2. var res = yield [
  3. Promise.resolve(1),
  4. Promise.resolve(2),
  5. Promise.resolve(3),
  6. ];
  7. console.log(res); // => [1, 2, 3]
  8. });
2.对象并行执行
  1. co(function *() {
  2. var res = yield {
  3. 1: Promise.resolve(1),
  4. 2: Promise.resolve(2),
  5. };
  6. console.log(res); // => { 1: 1, 2: 2 }
  7. });
3.返回promise
  1. co(function* () {
  2. return yield Promise.resolve(true);
  3. }).then(function (val) {
  4. console.log(val);
  5. }, function (err) {
  6. console.error(err.stack);
  7. });
  8. // 下面是可以返回一个常规的函数,同时也是一个promise对象
  9. var fn = co.wrap(function* (val) {
  10. return yield Promise.resolve(val);
  11. });
  12. fn(true).then(function (val) {
  13. });

参考

generator
koa官网
koa教程
co

感谢您的阅读!
如果看完后有任何疑问,欢迎拍砖。
欢迎转载,转载请注明出处:http://www.yangrunwei.com/a/48.html
邮箱:glowrypauky@gmail.com
QQ: 892413924