美文网首页前端开发
Node.js生态:Connect框架

Node.js生态:Connect框架

作者: chend0316 | 来源:发表于2019-04-30 02:02 被阅读0次

    Connect是一个中间件框架,负责管理、调度中间件,中间件的思想最早源于Ruby的Rack框架。

    Connect的代码非常少,只有200多行,因此我强烈建议你去阅读Connect的源码。你会看到Connect做的事情非常少,它的目的就是为了让其它框架基于自己实现更丰富的功能,事实证明这个策略是成功的。

    虽然Connect早期也自带了一些中间件实现,但从核心功能上来说Connect不需要自带中间件。从3.0之后Connect自带的中间件就被移到单独的项目了,所以现在的Connect本身没有提供任何中间件,这也是最新的Connect代码量很少的原因。

    Connect框架基本用法

    中间件是一个函数,函数原型是function (req, res, next) {}。为了更好地理解,我们下面实现几个简单的中间件,并将这几个中间件串联起来构成一个Web应用。该应用的功能是在网页上输出"Hello World",如果用户通过URL Get参数指明了自己的名字那么就输出"Hello 名字"。

    var connect = require('connect')
    var http =  require('http')
    
    // 这个中间件的功能是:将用户的HTTP请求打印在控制台上
    function logger(req, resp, next) {
        console.log('%s, %s', req.method, req.url)
        console.log(req.params)
        next()  // 将用户请求继续传递给下一个中间件处理
    }
    
    // 这个中间件的功能是:不管用户访问什么,都返回一个"Hello World"信息给用户
    function hello_world(req, resp, next) {
        resp.setHeader('Content-Type', 'text/plain')
        resp.end('Hello World')
        // 这里不调用next(),说明用户请求被这个中间件“拦截”了,不再继续传递给下一个中间件处理
    }
    
    // 这个中间件的功能是:将用户URL的参数解析并存放在req.url_params
    // 例如用户浏览器输入 http://localhost:3000?name=chend&age=24
    // 那么req.url_params就会变成: {'name': 'chend', 'age': '24'}
    function parse_url_parameter(req, resp, next) {
        req.url_params = {}
        if (req.url.indexOf('?') != -1) {
            var params_string = req.url.substr(req.url.indexOf('?') + 1)
            var params_arr = params_string.split('&')
            params_arr.forEach(function(param) {
                var key = param.substr(0, param.indexOf('='))
                var val = param.substr(param.indexOf('=') + 1)
                req.url_params[key] = val
            })
        }
        next()
    }
    
    // 这个中间件的功能是:从用户输入的URL Get参数中读取name变量,然后返回"Hello <name>"给用户,如果用户的URL没有name变量就不做任何事情
    // 例如用户在浏览器输入`http://localhost:3000/?name=chend`,那么我们会返回"Hello chend"给用户
    function hello(req, resp, next) {
        if (req.url_params && req.url_params.name) {
            resp.setHeader('Content-Type', 'text/plain')
            resp.end('Hello ' + req.url_params.name)
        } else {
            // 本中间件无法处理,就调用next()将用户请求传递给下一个中间件处理吧
            next()
        }
    }
    
    var app = connect()
    // 将上面定义的4个中间件按照这样的顺序串联起来,再次强调是按照顺序的
    app.use(logger).use(parse_url_parameter).use(hello).use(hello_world)
    
    http.createServer(app).listen(3000)
    

    Connect实现原理

    因为Connect核心逻辑很简单,我们这里就直接实现一个精简版的Connect帮助大家理解它是怎么工作的。

    我们知道Node.js自带的http模块是这样用的(业务要实现handle函数):

    var http = require('http')
    
    var handle = function(req, resp) {
        resp.writeHead(200, {'Content-Type': "text/plain"})
        resp.end("Welcome!")
    }
    
    var server = http.createServer(handle)
    server.listen(3000)
    

    下面我们定义一个app对象,能够像handle那样被当作函数一样调用,又能实现更加复杂的功能:

    function createServer() {
        var app = function (req, resp) {
            app.handle(req, resp)
        }
        app.queue = []
        app.handle = function handle(req, resp) {
            // 当用户在浏览器敲回车,http模块会调用一次该函数
            var index = 0
            var queue = this.queue
            function next() {
                var layer = queue[index++]
                if (!layer) { return }  // 所有路由规则遍历完毕
                if (layer.route != req.url) {  // 路由匹配功能
                    return next()
                }
                layer.handle(req, resp, next)  // next传递给业务中间件,由中间件决定是否调用next来传递给下一个中间件
            }
            next()  // 调用一次next,就一次
        }
        app.use = function use(path, fn) {
            this.queue.push({ route: path, handle: fn })
        }
    
        return app
    }
    
    module.exports = createServer
    

    Connect官方实现的中间件

    光有Connect这个中间件框架还不够,真正实现业务逻辑的是中间件本身。本章介绍由Connect/Express团队维护的一些官方中间件,利用这些中间件可以组成一个强大的Web应用。

    • body-parser为后续中间件提供req.bodyreq.files变量。
    • compression可以用gzip压缩HTTP响应,让用户感觉网页加载很快。
    • connect-timeout可以设置一个倒计时;后续中间件可以通过req.timedout这个布尔变量判断是否超时,也可以通过req.clearTimeout来取消倒计时;其原理是用过Node.js自带的setTimeout()clearTimeout()实现。
    • cookie-parser为后续中间件提供req.cookiesreq.signedCookies
    • cookie-session为后续中间件提供req.session
    • 等等

    相关文章

      网友评论

        本文标题:Node.js生态:Connect框架

        本文链接:https://www.haomeiwen.com/subject/vhbpnqtx.html