zoukankan      html  css  js  c++  java
  • 重构

    所有的URL处理函数都放到app.js里显得很乱,而且,每加一个URL,就需要修改app.js。随着URL越来越多,app.js就会越来越长。

    如果能把URL处理函数集中到某个js文件,或者某几个js文件中就好了,然后让app.js自动导入所有处理URL的函数。这样,代码一分离,逻辑就显得清楚了。最好是这样:

    url2-koa/
    |
    +- .vscode/
    |  |
    |  +- launch.json <-- VSCode 配置文件
    |
    +- controllers/
    |  |
    |  +- login.js <-- 处理login相关URL
    |  |
    |  +- users.js <-- 处理用户管理相关URL
    |
    +- app.js <-- 使用koa的js
    |
    +- package.json <-- 项目描述文件
    |
    +- node_modules/ <-- npm安装的所有依赖包

    于是我们把url-koa复制一份,重命名为url2-koa,准备重构这个项目。

    我们先在controllers目录下编写index.js

    var fn_index = async (ctx, next) => {
        ctx.response.body = `<h1>Index</h1>
            <form action="/signin" method="post">
                <p>Name: <input name="name" value="koa"></p>
                <p>Password: <input name="password" type="password"></p>
                <p><input type="submit" value="Submit"></p>
            </form>`;
    };
    
    var fn_signin = async (ctx, next) => {
        var
            name = ctx.request.body.name || '',
            password = ctx.request.body.password || '';
        console.log(`signin with name: ${name}, password: ${password}`);
        if (name === 'koa' && password === '12345') {
            ctx.response.body = `<h1>Welcome, ${name}!</h1>`;
        } else {
            ctx.response.body = `<h1>Login failed!</h1>
            <p><a href="/">Try again</a></p>`;
        }
    };
    
    module.exports = {
        'GET /': fn_index,
        'POST /signin': fn_signin
    };

    这个index.js通过module.exports把两个URL处理函数暴露出来。

    类似的,hello.js把一个URL处理函数暴露出来:

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

    现在,我们修改app.js,让它自动扫描controllers目录,找到所有js文件,导入,然后注册每个URL:

    // 先导入fs模块,然后用readdirSync列出文件
    // 这里可以用sync是因为启动时只运行一次,不存在性能问题:
    var files = fs.readdirSync(__dirname + '/controllers');
    
    // 过滤出.js文件:
    var js_files = files.filter((f)=>{
        return f.endsWith('.js');
    });
    
    // 处理每个js文件:
    for (var f of js_files) {
        console.log(`process controller: ${f}...`);
        // 导入js文件:
        let mapping = require(__dirname + '/controllers/' + f);
        for (var url in mapping) {
            if (url.startsWith('GET ')) {
                // 如果url类似"GET xxx":
                var path = url.substring(4);
                router.get(path, mapping[url]);
                console.log(`register URL mapping: GET ${path}`);
            } else if (url.startsWith('POST ')) {
                // 如果url类似"POST xxx":
                var path = url.substring(5);
                router.post(path, mapping[url]);
                console.log(`register URL mapping: POST ${path}`);
            } else {
                // 无效的URL:
                console.log(`invalid URL: ${url}`);
            }
        }
    }

    如果上面的大段代码看起来还是有点费劲,那就把它拆成更小单元的函数:

    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);
        }
    }
    
    addControllers(router);

    确保每个函数功能非常简单,一眼能看明白,是代码可维护的关键。

    Controller Middleware

    最后,我们把扫描controllers目录和创建router的代码从app.js中提取出来,作为一个简单的middleware使用,命名为controller.js

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

    这样一来,我们在app.js的代码又简化了:

    ...
    
    // 导入controller middleware:
    const controller = require('./controller');
    
    ...
    
    // 使用middleware:
    app.use(controller());
    
    ...

    经过重新整理后的工程url2-koa目前具备非常好的模块化,所有处理URL的函数按功能组存放在controllers目录,今后我们也只需要不断往这个目录下加东西就可以了,app.js保持不变。

  • 相关阅读:
    为了你,我一定要写诗
    哈佛成功金句25则(看一遍,都会很有收获!)
    成功者的十三个“百万元习惯”
    商业领袖的7大人脉宝典
    我为你疯狂
    秋收,为何我收获的只有泪水
    又逢中秋月
    今宵谁与共
    26句话,让你豁然开朗
    田彩蝶(帮别人名字作诗)
  • 原文地址:https://www.cnblogs.com/cangqinglang/p/10238440.html
Copyright © 2011-2022 走看看