zoukankan      html  css  js  c++  java
  • 极简Node教程-七天从小白变大神(二:中间件是核心)

    当我们只引入express时,前述的那些功能都是没有启用的。那么,如何将这些功能添加进来呢?express通过其中间件机制实现了这些功能的管理。每一个中间件对应一个功能,而中间件可以是第三方库,也可以是我们的业务逻辑。以后我们会经常用到express的中间件。下面我们来简单介绍其工作机制:

    你可以把一个中间件理解为一个处理函数(从请求产生响应),通过app.use(<中间件名称>)方法将中间件添加到一个列表中。当HTTP请求到达时,Express会依次调用队列中的中间件,它们的功能便会依次执行,直到某个中间件返回了HTTP响应为止。

    详情

                                                                      ---- 以上来自互联网
    
    上集回顾

    核心归纳(重要的务必看三遍)

    1. 中间件是一种功能的封装方式,具体来说就是封装在程序上处理HTTP请求的功能。
    2. 中间件是在管道中执行的。你可以想象一个送水的真实管道。水从一端泵入,然后在到达目的地之前还会经过各种仪表与阀门。这个比喻很重要的一部分就是顺序问题,你把压力表放在阀门之前和之后效果是不同的。
    3. 在管道最后面我们会放一个来处理和前面任何路由都不匹配的请求。也就是错误处理中间件一般返回状态吗404.
    4. 最最重要的就是next()的调用,如果一个中间件你不调用next()那么请求就不会传递出去因为已经被终止了。

    favicon的处理

    favicon是一个网站的图标,很多浏览器都支持这个功能。浏览器获取通过一个约定好的地址去获取该favicon,并将icon放在地址的前面作为标识。现在再访问一下 http://localhost:3000/ ,看看最上面网站名称前面是不是有一个空白文件的favicon。现在让我们来替换掉它。

    首先还是添加依赖npm install serve-favicon --save,然后在server.js中添加以下代码:

    var favicon = require('serve-favicon');
       app.use(favicon(__dirname + '/favicon.ico'));
    

      

    然后在项目根目录下面添加一个facicon.ico,这个图标文件可以自己去制作或者去素材网站上寻找.

    然后重启服务器,浏览器输入网址:

       http://localhost:3000/favicon.ico
    

      

    就能看到你的网站图标了

    自己编写中间件(当然要靠自我奋斗,同时呢...)

    通用中间件

    我们来写一个通用的可以处理任何请求的中间件,编写中间件其实可以粗浅的理解为以下结构:

      app.use(xxx());      // xxx()可以是个匿名函数也可以是第三方中间件那样:
            app.use(bodyParser())      // 
    

      

    下面我们写一个打印请求时间的中间件(匿名结构):

       app.use(function (req, res, next) { console.log('Time:',     
             Date.now()); next();});  
    

      

    把上面这个中间件放在server.js 引用模块后的最上方,它就可以第一时间上(各种意义)打印请求时间了,现在重启服务器,重载网页就能在命令行看到请求的时间,不出意外应该有两次吧?,至于为什么,交给聪明的读者吧!

    挂载中间件

    挂载可以从以下例子理解:

       // 挂载至 /user/:id 的中间件,任何指向 /user/:id 的请求都会执行它
    app.use('/user/:id', function (req, res, next){
    console.log('Request Type:', req.method); 
     next();});  
    

      

    也就是说只有请求开头user/:id 才会被这个中间件处理,如果不是则会被忽略。
    此外上述的req.method是指请求的方式例如:get,post,put,delete
    现在把这个中间件添加到第一个中间件下面,然后重启服务器,浏览器输入:

     localhost:3000/user/5
    

      

    虽然页面应该没什么反应,但是命令行会有比较满意的答复。

    中间件与模块引入

    在谈到这个问题之前,首先必须了解NodeJS的exports引入机制:
    我们在routes目录下新建一个文件导出一个用来计算汇率兑换的函数:

      // toUSD.js
        var rate = 6.4;
       export.toUSD  = function(count){
           return count * rate;   
      } 
    

      

    保存以后,我们在server.js引用其:

       var toUSD = require('./routes/toUSD');   // 可以省略js后缀
       console.log(toUSD(100));                           //  return 640 
    

      

    我们干了什么呢?

    我们把计算汇率的函数引用到入口文件这里,然后调用,没有暴露出rate的值,这样符合开闭原则。
    如果一个函数你不想暴露里面的细节,而且想多次复用,那么可以采用以上的方式。

    那么我们怎么结合模块与中间件呢?

    必须清楚的了解中间件是一个函数,而这个中间件是一个函数。
    比如我们又有一个模块叫做:

        //  ./routes/foo.js
          module.exports = function(req,res,next){
              if(Math.random() > 0.5) next();
              res.send('the random num less than 0.5')   
    }
    

      

    如果随机数大于0.5我们直接到下一个中间件,跳过响应。不然我们就直接响应请求,后面的中间件将都不会执行。

    现在在server.js引入它:

     //var foo = require('./routes/foo.js');
         //  app.use(foo())
    

      

    或者简单粗暴:

      app.use(require('./routes/foo.js'));
    

      

    但是这样写,弊端就是随着项目不断的扩大,函数数量及文件数量会极具的增加,这样会使我们的项目看起来非常杂乱。如果你不希望你有非常的require语句..以及二次修改时层峦叠嶂的目录函数的话...

    怎么优雅的写中间件呢?(知乎体)

    输出一个以中间件为属性的对象。形如下面:

    // ./routes/xxx.js
          module.exports = {
               aaa: function(req,res,next){
                         // doing sth     
               },
               bbb: function(req,res,next){
                       //doing sth
               }      
    };
     // server.js var xxx = require('./routes/xxx.js'); app.use(xxx.aaa); app.use(xxx.bbb); 

      

    
    

    谢邀,...........

    这样我们完美优雅的解决了这个问题
    你为什么写中间件这么熟练啊????? 你写过多少次啊???

    小结

    中间件是Express的核心,路由处理是Express的看家本领,两者都要好好掌握,首先把官方教程批判一番方为正道。



    作者:颜卿今天Coding了吗
    链接:https://www.jianshu.com/p/aa31761deae3
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    react-router-dom中route报错处理 Invalid prop 'component' supplied to 'Route': the prop is not a valid React component
    解决create-react-app在ie中打开页面空白的兼容性问题
    使用Echart VUE实战开发-大数据疫情地图
    深克隆 闭包 面向对象总结
    数组去重 数组排序的方法 js实现
    JAVA常用知识总结(六)——Mybatis
    时间复杂度和空间复杂度
    JAVA常用知识总结(五)——Linux
    JAVA常用知识总结(三)——JAVA虚拟机
    JAVA常用知识总结(二)
  • 原文地址:https://www.cnblogs.com/guozhe/p/8194392.html
Copyright © 2011-2022 走看看