zoukankan      html  css  js  c++  java
  • node.js-express的app.use()初步理解

    先看最简单的node的hello world

    var http = require('http');
    http.createServer(function (req, res) {
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('Hello World
    ');
    }).listen(1337);

    上面这段就是来一个请求,就用传给createServer的匿名函数来处理请求。

    使用Express的代码

    var app = express();
    //...中间忽略
    http.createServer(app).listen(app.get('port'), function(){
        console.log('Express server listening on port ' + app.get('port'));
    });

    对比可以看出,执行express()后,会返回一个函数,赋值给app,app的签名应该为:

    function(req,res){//...}

    然后请求都会被app这个函数处理(因为这个app是执行express后的结果,下面将不加区分的使用app和express两个词)。

    可以认为,在express内部,有一个函数的数组,暂时叫这个数组tasks,每来一个请求express内部会依次执行这个数组中的函数(这里说依次并不严谨,每个函数必须满足一定条件才行,这个后面说),应该可以想到,在这个函数数组里,每个函数的签名应该像下面那样:

    function(req,res){//...}

    但是,实际上是:

    function(req,res,next){//...}

    这个next,是指下一个函数。后面我们会写一些试验来体验一下这个next,先总结一下:

    对于一个典型的使用express的app.js,做了以下几件事

    • 1.导入相关模块
    • 2.执行过 var app = express() 后,
      • 使用app.set 设置express内部的一些参数(options)
      • 使用app.use 来注册函数,可以简单的认为是向那个(被我叫做)tasks的数组进行push操作
    • 3.通过http.createServer 用app来处理请求

    试验一: 向express中注册自定义函数

    注册进express中的函数,需要满足(请见下面更正)

    1.长成下面这个样子:

    function(req,res,next){
        //...我们自己的逻辑
        next();
    }

    2.app.use(customerFunc) 要写在下面两句的前面:

    app.use(app.router);
    app.use(express.static(path.join(__dirname, 'public')));

    关于第2点,是因为路由后或请求静态资源后,一次请求响应的生命周期实质上已经结束,加在这后面进行请求处理,没有任何意义。

    关于第1点,写点代码就好了:

    app.use(function(req,res,next){
        console.log("111");
        next();
    });

    如果不写next(),那么后面注册的函数就不会执行,运行试一下就知道了。

    再来一个:

    app.use(function(req,res,next){
        console.log('111');
        next();
        console.log('222');
    });
    
    app.use(function(req,res,next){
        console.log("333");
        next();
    });

    那么控制台的输出的顺序是:111 333 222

    更正:

    上面说,自定义的函数应该满足两个条件,一般使用是那样。但是,也可以两个都不满足。。。比如,自定义函数可以是4参数的,放在最后做通用error处理。:

    app.use(app.router);
    app.use(express.static(path.join(__dirname, 'public')));

    在上面两句之后可以加一个:

    app.use(function(err,req,res,next){
        if(err){
             //自己的处理错误的逻辑
             console.log(err.message);
             console.log(err.stack);
             res.end('404')  
        }
    });

    试验二: next()的工作原理

    在理解的上面的过程后,能不能不借助express,自己实现上面的过程呢,主要是怎么处理next()那一块:

    function express(){
        var funcs = [];
    
        var expr = function(req,res){
            var i = 0;
            function next(){            
                var task = funcs[i++];
                if(!task) return;
                task(req,res,next);
            }
            next();
        }
        expr.use=function(f){
            funcs.push(f);
        }
        return expr;
    }
    var app = express();
    
    app.use(function(req,res,next){
        console.log('haha');
        next();
    });
    app.use(function(req,res,next){
        console.log('hehe');
        next();
    });
    app.use(function(req,res){
        res.end("there is nothing happened");
    });
    
    http.createServer(app).listen('3000', function(){
      console.log('Express server listening on port 3000');
    });

    启动服务后,每来一个请求,控制台会依次输出haha hehe,然后浏览器是there is nothing happened

    当然如果要更深一步,可以去看原代码,实际上这一部分的主要代码是在connect中的,在connect/lib/proto.js 这个源文件中,主要是app.use,和app.handle 两个函数中。

  • 相关阅读:
    Ant.OutputIsUnreadableCode
    Android.HowToDesignPluginArchitectureInAndroidApp
    Java.FamousBlogs
    Java.WeakReference-SoftReference-PhantomReference
    DataStructure.BloomFilter
    Android.HowToDefineCustomView
    Android.Study.Question
    Android.PublishApplication
    Android.Libraries
    Site.AboutHardware
  • 原文地址:https://www.cnblogs.com/fydxx/p/6707875.html
Copyright © 2011-2022 走看看