koa之处理器模块化

来源:互联网 发布:淘宝捉猫猫时装碎片 编辑:程序博客网 时间:2024/05/19 02:26

在之前的文章中,已经可以实现url与处理器函数之间的映射。但是把代码直接写在app.js中似乎十分不妥,一个是会造成app.js文件的冗长,二是不好扩展和修改。为了解决这个问题,可以将处理函数封装为一个个模块,在启动服务器时再将url和处理器模块映射起来。这样就可以解决如上所述的问题。

但是除了将处理器函数封装为单独的模块之外,还需要一段将url和处理器模块映射起来的代码用于在服务器启动的时候执行。

首先创建一个controllers目录,在此目录下编写处理器模块。一个简单的示例如下:

var hello = async (ctx, next) => {
    var name = ctx.params.name;
    ctx.response.body = `<h1>Hello, ${name}!</h1>`;
};

module.exports = {
    'GET /hello/:name':hello
};

然后再加上一个controller.js模块,在此模块中映射url和处理器模块,代码如下:

const fs = require('fs');

function addMapping(router, mapping) {
    for (var url in mapping) {
        if (url.startsWith('GET ')) {
            var path = url.substring(4);
            router.get(path, mapping[url]);
            console.log(`register URL mapping: GET ${path}`);
        } else if (url.startsWith('POST ')) {
            var path = url.substring(5);
            router.post(path, mapping[url]);
            console.log(`register URL mapping: POST ${path}`);
        } else {
            console.log(`invalid URL: ${url}`);
        }
    }
}

function addControllers(router) {
    var files = fs.readdirSync(__dirname + '/controllers');
    var js_files = files.filter((f) => {
        return f.endsWith('.js');
    });

    for (var f of js_files) {
        console.log(`process controller: ${f}...`);
        let mapping = require(__dirname + '/controllers/' + f);
        addMapping(router, mapping);
    }
}

module.exports = function (dir) {
    let
        controllers_dir = dir || 'controllers', // 如果不传参数,扫描目录默认为'controllers'
        router = require('koa-router')();
    addControllers(router, controllers_dir);
    return router.routes();
};

controller.js文件一般不需要变动。接下来是app.js的代码:

'use strict';

const Koa = require('koa');
// 创建一个Koa对象表示web app本身:
const app = new Koa();

const controller = require('./controller');


app.use(controller());
// 在端口3000监听:
app.listen(3000);
console.log('app started at port 3000...');

可以看到app.js的代码简化了许多,而且即使有代码的修改和扩展也不会受到影响。真正做到了开闭原则。