• Node.js_06 express


    一、初探

    1 express是什么

    • Express.js 框架是目前最流行的node.js后端框架之一, 相当于jQuery和js之间的关系;
    • Express 不对 Node.js 已有的特性进行二次抽象,我们只是在它之上扩展了 Web 应用所需的基本功能;
    • 功能类似的后端框架:Koa.js, egg.js, hapi.js

    2 安装

    • 进入应用目录

    • npm init 命令为你的应用创建一个 package.json 文件

    • 安装 Express 并将其保存到依赖列表中 npm install express --save

      如果只是临时安装 Express,不想将它添加到依赖列表中,只需略去 --save 参数即可 npm install express

    3 Express 应用生成器

    通过应用生成器工具 express 可以快速创建一个应用的骨架。

    • 安装 npm install express-generator -g ,这个可以在cmd 里执行,全局安装,全局安装以后在哪儿都可以直接用了。

    常用操作: express -h -h 选项可以列出所有可用的命令行选项

    • 新建一个文件夹demos, 在该文件夹下执行 express --view=ejs demo1 设置视图模板, 这句执行完毕后,接下来怎么执行,命令行会提示
    • 安装所有依赖包 npm install
    1. 设置视图模板 express --view=ejs demo1

    2. 启动应用:

      • MacOS 或 Linux 平台: DEBUG=myapp npm start
      • Windows 平台: set DEBUG=myapp & npm start
      • 在浏览器中打开 http://localhost:3000/ 网址就可以看到这个应用了
    3. 通过 Express 应用生成器创建的应用一般都有如下目录结构:

    4.中间件

    通过app 根据路径处理 客户端传来的 get post 请求:

    // 1 引入
    const express = require('express');
    
    // 2 创建一个server
    const app = express();
    
    // 3 通过app 根据路径处理 客户端传来的 get post 请求
    app.get('/',(req,res)=>{
        res.write('<h1>there is two ways,the one is the right way ,the other way is the easy way!</h1>');
        res.end();
    });
    
    app.get('/pub',(req,res)=>{
        res.write('<p>there is a way!</p>');
        res.end();
    });
    
    // 
    app.get('/it', (req, res)=>{
        console.log(req.url);
        res.write('<h2>it</h2>');
        res.end();
    });
    
    // 4 开启监听
    app.listen(3000,()=>{
        console.log('server is running');
    });
    
    /*
    
    访问:http://localhost:3000/   ----there is two wa......
    访问: http://localhost:3000/pub ---- there is a way!  
    访问:http://localhost:3000/it?name=jack&age=12  server端打印: /it?name=jack&age=12
    
    */
    

    app.use:

    const express = require('express');
    const app = express();
    
    // 中间件
    app.use((req,res,next)=>{
        console.log(111);
        next();  // next() 后,才会继续往下面执行,否则就会卡在这里,后面的也不会执行了
    });
    
    app.use((req,res,next)=>{
        console.log(222);
        next();
    });
    
    app.use((req,res,next)=>{
        console.log(333);
        next();
    });
    
    app.get('/pub',(req,res,next)=>{
        console.log('pub file');
        next();
    });
    
    app.get('/',(req,res,next)=>{
        console.log('aaa');
        res.write('<h1>hello a</h1>');
        res.end();
    });
    
    app.listen(3000,()=>{
        console.log('server is running');
    })
    
    // 直接访问 http://localhost:3000/  打印
    /*
    server is running
    111
    222
    333
    aaa
    */
    /*
    * 访问  http://localhost:3000/pub
    *
    * server is running
    111
    222
    333
    pub file
    
    * */
    

    用中间件写日志:

    const express = require('express');
    const fs = require('fs');
    const app = express();
    
    app.use((req,res,next)=>{
        const lg =
    `
    ---------------------------
    请求方式:${req.method},
    请求路径:${req.url},
    请求时间:${new Date}
    --------------------------- 
    
    
    `
    
        // 写入文件
        fs.appendFile('log.txt',lg,(err)=>{
            if(err){
                console.log('log write failed');
            }else {
                console.log('log write success');
            }
        });
        res.end()
    
    })
    
    
    app.listen(3000,()=>{
        console.log('server is running..');
    })
    
    /*
    log.txt:
    ---------------------------
    请求方式:GET,
    请求路径:/,
    请求时间:Tue Dec 25 2017 12:52:27 GMT+0800 (GMT+08:00)
    --------------------------- 
    */
    

    5.静态资源文件夹配置

    const express = require('express');
    const fs = require('fs');
    const path = require('path');
    
    const app = express();
    
    // 配置静态资源文件夹
    app.use(express.static(path.join(__dirname,'public'))); //将public 文件夹作为静态资源文件夹
    
    app.get('/',(req,res,next)=>{
        console.log(path.join(__dirname, 'public'));
        res.end();
        next();
    });
    
    app.listen(3000, ()=>{
        console.log('server is running..');
    });
    
    /*
    * 访问 http://localhost:3000/images/1.jpg , 就可以访问到public/images/1.jpg 文件了
    * 访问 http://localhost:3000/  打印: E:hfivegd_codep8d7demosdemo1public
    * */
    

    6 模板引擎

    目录结构:

    engine.js:

    let express = require('express');
    let path = require('path');
    let app = express();
    
    // 1 指定视图所在位置
    app.set('views',path.join(__dirname,'views'));
    
    // 2. 注册模板引擎
    app.set('view engine','ejs');
    
    app.get('/',(req,res)=>{
        res.render('index',{"lists":["黄飞鸿","张择端","霍华德"]}); //这里放json的数据,开发中,将数据从数据库取出传这里即可。
    
    });
    app.listen(3000);
    

    index.ejs:

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
    <ul>
        <% for(var i=0; i<lists.length;i++){%>
        <li><%=lists[i] %></li>
        <%}%>
    </ul>
    </body>
    </html>
    

    运行结果:


    express 如何处理错误,如果处理找不到页面的情况,如下代码实现与 express帮我们生成的代码结构类似,可以帮我们更好的理解express 自动生成后成品结构。

    const express = require('express');
    const fs = require('fs');
    const app = express();
    
    app.get('/',(req,res,next)=>{
        try {
            const data = JSON.parse('{"name":}'); // 这里设置让程序报错
            console.log(data);
            res.json(data);
        }catch (e) {
            next(e);
        }
    });
    
    app.get('/a',(req,res,next)=>{
        res.end('hello,this is directory: a ');
    });
    
    /**
     * 统一处理错误,记录日志
     */
    app.use((err,req,res,next)=>{
        const err_log = `
        ----------------------
        错误名: ${err.name},
        错误消息: ${err.message}, 
        错误时间: ${new Date()}, 
        错误堆栈: ${err.stack}
        ----------------------
        `;
        fs.appendFile('./err_log.txt',err_log,(err)=>{
           res.writeHead(500,{"Content-Type": "text/html;charset=utf-8"});
           res.end('500,服务器内部错误');
        });
    });
    
    // 404
    app.use((req,res,next)=>{
        res.writeHead(404, {"Content-Type": "text/html;charset=utf-8"});
        res.end('您当前访问的页面不存在!!!!');
    });
    
    app.listen(3000,()=>{
        console.log('running..');
    });
    

    执行结果:

    1、访问 http://localhost:3000/ ,页面显示:500,服务器内部错误 ,并记录日志

    2、访问 http://localhost:3000/a ,页面显示:hello,this is directory: a

    3、访问 http://localhost:3000/b,页面显示:您当前访问的页面不存在!!!! ,并记录日志

    二、express + socket.io

    1、搭建

    全局安装过 generator 后,执行如下命令,创建项目文件

    express --view=ejs chat
    

    自动生成如下结构:

    然后,安装依赖

    cd chat
    npm install
    

    系统会提示:

    run the app:
     > SET DEBUG=chat:* & npm start
    
    

    运行它有两种方式,一种就是 执行 ``` npm start ``1

    或者,运行bin 目录下的 www.js 文件

    2、简要说明

    此处只记录简要内容,不记录详细细节

    引入路由文件:

    中间件:

    chat.js:

    3、 socket.io

    Socket.io 将 Websocket 和轮询( Polling )机制以及其它的实时通信方式封装成了通用的接口,并且在服务端实现了这些实时机制的相应代码。

    H5 的新技术 Websocket 仅仅是 Socket.io 实现实时通信的一个子集。

    中文文档参考 : https://www.w3cschool.cn/socket/

    安装:

    npm install socket.io --save
    

    使用 socket.IO 的时候,需要生成一个 实例对象;
    生成这个实例对象的依赖原生 node 已经建立好的 httpServer 对象

    客户端socket.on()监听的事件:
    connect:连接成功
    connecting:正在连接
    disconnect:断开连接
    connect_failed:连接失败
    error:错误发生,并且无法被其他事件类型所处理
    message:同服务器端message事件
    anything:同服务器端anything事件
    reconnect_failed:重连失败
    reconnect:成功重连
    reconnecting:正在重连

    当第一次连接时,事件触发顺序为:connecting->connect;

    当失去连接时,事件触发顺序为:disconnect、reconnecting(可能进行多次)、connecting、reconnec、connect。

    demo 演示:

    chat.ejs:

    <ul id="chatList">
        <li class="service"><span class="chat-msg">1</span></li>
        <li class="custom"><span class="chat-msg">111111,!</span></li>
        <li class="service"><span class="chat-msg">2</span></li>
        <li class="custom"><span class="chat-msg">2222222</span></li>
    </ul>
    
    <script src="/socket.io/socket.io.js"></script>
    <script src="/lib/js/jquery-3.3.1.js"></script>
    <script>
        // 1建立连接
        var socket = io('http://localhost:3000');
        socket.on('connect', function (data) {
            console.log(data);
            // 1.1 打开通道
            socket.emit('open...');
        });
    
        //2.监听
        socket.on('msg',function (data) {
            console.log(data);
            dealWithMsg('service',data)
        });
    
        // 3 点击发送
        $('#btn_send').on('click',function () {
            // 3.1 发送消息给服务器
            socket.emit('msg',$('#msg').val());
            // 3.2 显示到界面
            dealWithMsg('custom',$('#msg').val());
            // 3.3 清空消息
            $('#msg').val('');
        });
    
        let dealWithMsg = (claaName,data)=>{
            // 1 创建标签
            let $liDom = $("<li>");
            $liDom.attr({
                'class':claaName
            });
    
            // 创建span
            let $spanDom = $("<span>");
            $spanDom.attr({
               "class":"chat-msg"
            });
    
            $spanDom.text(data);
            $liDom.append($spanDom);
            $('#chatList').append($liDom);
    
    
            // 2. 让滚动条在最底部
            // $('#chatList')[0] 是把它从jquery 转成 js 了,这样就可以拿到scrollheight
            let scoreHeight = $('#chatList')[0].scrollHeight;
            $('#chatList').scrollTop(scoreHeight);
            console.log(scoreHeight);
        };
    
    </script>
    

    www.js:

    ...............
    // 1. 引入包
    const socketIO = require('socket.io');
    // 2. 针对 http server  生成 socket.IO  实例对象
    let io = socketIO(server);
    
    // 3.建立连接
    io.on('connection',(socket)=>{
        console.log('建立连接成功');
        // 3.1 返回消息
        socket.emit('msg','欢迎找我talk!');
    
        // 3.2 接收客户端的消息
        socket.on('msg',(data)=>{
            console.log(data);
            let msg = backMsg(data);
            socket.emit('msg',msg);
        });
    });
    
    // 4. 根据用户输入, 返回信息
    let backMsg = (data)=>{
        let msg = null;
        switch (data){
            case '在吗':
                msg =  '我在呢...';
                break;
            case '1':
                msg =  '1111';
                break;
            case '2':
                msg =  '2222!';
                break;
            case '3':
                msg =  '3333!';
                break;
            case '4':
                msg =  '44444444';
                break;
            default:
                msg = 'what are you talking about....';
        }
        return msg;
    };
    
    

  • 相关阅读:
    JS中的钩子(hook)机制与实现
    Java 之 注解的定义
    Java 网络编程案例:使用 MulticastSocket 实现多点广播
    Java 基于 UDP 协议的网络编程
    Java 网络编程案例四:多个客户端群聊
    Java 网络编程案例三:多个客户端上传文件
    Java 网络编程案例二:多台客户端与服务器之间的多次通信
    Java 网络编程案例一:一台客户端与服务器单次通信
    Java 之 网络常用API
    Java 之 网络编程基础知识
  • 原文地址:https://www.cnblogs.com/friday69/p/10153021.html
Copyright © 2020-2023  润新知