zoukankan      html  css  js  c++  java
  • node.js原生后台进阶(二)

    上一章讲到怎么样用原生node.js来获取GET、POST(urlencoded,formData)的参数,这一次我们更进一步,讲一下以下的点:

    1.压缩(zlib)

    2.流(stream)

    3.路由


    一、压缩

    所有网站其实在发送到我们的客户端的时候,数据都是经过压缩的,不然会造成大量的流量损失,流量可都是钱啊~~~

    node里面有一个模块叫zlib,是专门用来压缩数据的,而我们最常用的就是gzip

    const zlib = require('zlib');
    //创建gz对象,之后就可以对流进行压缩处理了
    let gz = zlib.createGzip();

    二、流

    为什么要用流处理呢?例如之前的写法,fs.readFile是读取完整个文件才把整个文件的data输出的,这样就会造成一个机器资源使用不充分的问题:

    一开始读取文件的时候,磁盘在高速工作,但是带宽却空闲着,

    之后读取完文件后,带宽在忙碌传输,磁盘却空闲了。

    用流来处理,就可以做到“磁盘读到多少就用带宽传多少”,充分利用服务器的资源

    //创建一个读取流
    let rs = fs.createReadStream(`www${pathname}`);
    let gz = zlib.createGzip();
    //书写响应头,告诉浏览器我们的数据格式是经过压缩的gzip
    res.setHeader('Content-Encoding','gzip');
    //读取流先传给gz,再传给响应流
    rs.pipe(gz).pipe(res);
    rs.on('error',err=>{
        //如果错误,要把之前的响应头去掉,不然浏览器会解析错误
        res.removeHeader('Content-Encoding');
        res.writeHeader(404);
        res.write('not found!!');
        res.end();
    })

    三、路由

    所谓路由,就是接口的地址入口,我们大可以这样写:

    switch(pathname){
      case '/login':
          //...
       break;
      case '/reg':
          //...
       break;
      default:
          //...
       break;
    }

    不过这样写,导致路由和功能代码严重的耦合在一起,这显然不是我们想要的

    node给我们提供了一个叫EventEmitter的东西,实现了在js的响应式编程

    因为node.js的引用是单例的,因此我们可以先创建一个module作为全局的EventEmitter,router.js

    const Event = require('events').EventEmitter;
    
    module.exports = new Event();

    在server.js那加入EventEmitter的触发:

    const http = require('http');
    const fs = require('fs');
    const router = require('./libs/router');
    const url = require('url');
    const zlib = require('zlib');
    //在'./router/Users'上面注册了一些接口
    require('./router/Users');
    
    http.createServer((req,res)=>{
      let {pathname,query}=url.parse(req.url,true);
      req.query = query;
      res.send = msg=>{
        if(typeof msg!="string"&&!(msg instanceof Buffer)){
          msg = JSON.stringify(msg);
        }
        res.write(msg);
      }
      //router.emit会触发对应的接口,如果事先有注册对应的接口返回true,否则返回false,我们就认为这个请求是在请求文件
      if(!router.emit(pathname,req,res)){
        let rs = fs.createReadStream(`www${pathname}`);
        let gz = zlib.createGzip();
        res.setHeader('Content-Encoding','gzip');
        rs.pipe(gz).pipe(res);
        rs.on('error',err=>{
          res.removeHeader('Content-Encoding');
          res.writeHeader(404);
          res.write('not found!!');
          res.end();
        })
      }
    }).listen(8088);

    做完这些,我们就可以在多个模块来“注册”接口了

    const router = require('../../libs/router.js');
    
    let users = {
      rick : 123456
    };
    //注册一个叫'/login'的接口,在这里我们还可以添加上一篇博文的东西,接收GET、POST的参数,这里我只写了接收URL上的参数
    router.on('/login',(req,res)=>{
      let {name,pass} = req.query;
      if(!users[name]){
        res.send({code:1,msg:'user not found!'})
      }else if(users[name]!=pass){
        res.send({code:1,msg:'username or password is wrong'})
      }else{
        res.send({code:0,msg:'success'})
      }
      res.end();
    })
  • 相关阅读:
    XNA游戏编程等
    DirectX游戏编程(一):创建一个Direct3D程序
    POJ 1163 The Triangle(简单动态规划)
    web前段canvasjs图表制作一
    ubuntu 使用mysql
    Nginx+ uWSGI +django进行部署
    matplotlib如何绘制直方图、条形图和饼图
    matplotlib animation
    matplotlib 画图中图和次坐标轴
    matplotlib subplot 多图合一
  • 原文地址:https://www.cnblogs.com/amiezhang/p/8134164.html
Copyright © 2011-2022 走看看