connect 主要方法介绍

connect 主要的思路是给app函数添加一个stack的数组在数组中存放路由path以及handle方法的对象,通过向handle方法中传入next方法去把控制权交给执行的方法,我们可以选择next()执行这个下一个stack中的方法或是不调用结束本次请求。 下面我会详细讲解下这两个方法

创建一个app方法
function createServer() {
    function app(req, res, next) {
        app.handle(req, res, next);
    }
    // 添加方法
    merge(app, proto);
    merge(app, EventEmitter.prototype);
    app.route = '/';
    // 存放中间处理方法的栈
    app.stack = [];
    return app;
}
复制代码

每调用一次createServe方法就会生成一个app函数,然后通过proto 这个对象去给app添加一些方法。 下面的use方法就是给主流程添加中间件的方法。将处理方法存在stack的数组中,请求过来之后一次调用stack中的方法。

proto.use = function use(route, fn) {
    var handle = fn;
    var path = route;

    // 默认设置route 为 '/'
    if (typeof route !== 'string') {
        handle = route;
        path = '/';
    }

    // 如果对象有handle方法取对象的handle方法
    if (typeof handle.handle === 'function') {
        var server = handle;
        server.route = path;
        handle = function(req, res, next) {
            server.handle(req, res, next);
        };
    }

    // 如果是http的对象,获取监听的http的request的第一个事件方法
    if (handle instanceof http.Server) {
        handle = handle.listeners('request')[0];
    }

    // 去除路由最后一个/ 字符
    if (path[path.length - 1] === '/') {
        path = path.slice(0, -1);
    }

    // 将处理方法和路由压入app栈
    this.stack.push({ route: path, handle: handle });
    // 返回当前对象
    return this;
};
复制代码

proto.handle 方法是用来调用中间件处理方法的程序

proto.handle = function handle(req, res, out) {
    var index = 0;
    // 获取url的host
    var protohost = getProtohost(req.url) || '';
    var removed = '';
    var slashAdded = false;
    var stack = this.stack;
    // 对http请求去做最后一个处理的方法
    var done = out || finalhandler(req, res, {
        env: env,
        onerror: logerror
    });
    // 保存原始的url
    req.originalUrl = req.originalUrl || req.url;
    // 调用下一个处理函数,这个很重要
    function next(err) {
        if (slashAdded) { 
            // 去掉一开始的'/'
            req.url = req.url.substr(1);
            slashAdded = false;
        }
        if (removed.length !== 0) {
            // 还原url
            req.url = protohost + removed + req.url.substr(protohost.length);
            removed = '';
        }
        // 下一个处理方法
        var layer = stack[index++];
        // 调用处理结束方法
        if (!layer) {
            defer(done, err);
            return;
        }
        // 获取路径
        var path = parseUrl(req).pathname || '/';
        var route = layer.route;
        // 如果路径与路由不匹配则继续调用下一个方法处理
        if (path.toLowerCase().substr(0, route.length) !== route.toLowerCase()) {
            return next(err);
        }
        // skip if route match does not border "/", ".", or end
        var c = path[route.length];
        if (c !== undefined && '/' !== c && '.' !== c) {
            return next(err);
        }
        // trim off the part of the url that matches the route
        if (route.length !== 0 && route !== '/') {
            removed = route;
            // 截断url
            req.url = protohost + req.url.substr(protohost.length + removed.length);
            // ensure leading slash
            if (!protohost && req.url[0] !== '/') {
                req.url = '/' + req.url;
                slashAdded = true;
            }
        }
        // 调用中间件的处理方法
        call(layer.handle, route, err, req, res, next);
    }

    next();
};
复制代码

转载于:https://juejin.im/post/5c37104151882525a7242799

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值