node —— stream & EventEmitter & ejs

一、 stream

1. Node.js Stream中的四种流类型
  • Readable:可读操作
  • Writable:可写操作
  • Duplex:可读可写操作
  • Transform:操作被写入数据,然后读出结果
2. Stream对象的常用事件

注意: 所有Stream对象都是EventEmitter的实例。

  • data:当有数据可读时触发
  • end:没有更多的数据可读时触发
  • error:在接收和写入过程中发生错误时触发
  • finish:所有数据已被写入到底层系统时触发
3. 常见流操作

注意:若想将读出的所有内容写入文件中,由于事件操作具有异步性,故必须在读完后进行写入,故应在可读流的end事件触发后向文件写入

① 从流中读取数据
  1. 非一次性读取完文件中的所有数据
  2. 监听流的事件都是异步操作
步骤:
  1. 引入fs模块:const fs = require("fs")
  2. 创建可读流:let streamRead= fs.createReadStream(读取文件路径)
  3. 设置流的编码:streamRead.setEncoding("UTF-8")
  4. 处理流文件的事件:on
    streamRead.on("data",(res)=>{}):当有数据可读时触发。只要有数据可读就会触发,直到数据读取完成(当文件数据足够多时,会触发多次。res为本次读取的数据)
    streamRead.on("end",()=>{}):读取数据完成时触发
② 向文件中写入数据

一次性将数据写入文件
监听流的事件都是异步操作

步骤
  1. 引入fs模块:let fs = require("fs")
  2. 创建写入流:let streamWrite=fs.createWriteStream(写入文件的路径)
  3. 使用utf-8编码写入数据:streamWrite.write(写入的数据,'UTF-8')
  4. 写入结束关闭流:streamWrite.end()
  5. 处理流文件的事件:on
    streamWrite.on("finish"()=>{}):写入完成时触发
//从一个文件读出数据,再写到另一个文件
  let streamData = fs.createReadStream("public/stu.txt");
    let resData = "";
    streamData.setEncoding("UTF-8");
    streamData.on("data", (res) => {
        //会一直执行,直到数据读取完成
        console.log("有数据可读");
        resData += res;
    })
    streamData.on("end", () => {
        console.log("数据读取完成");
        //创建写入流  必须在读完时才创建写入流,否则异步操作,resData为空
        let writeStream = fs.createWriteStream("public/demo.txt");
        //设置写入数据以及编码
        writeStream.write(resData, "UTF-8")
        //写入完成,结束流
        writeStream.end();
        writeStream.on("finish", () => {
            //写入流完成时触发
            console.log("数据写入完成")

        })
    })
    streamData.on("error", () => {
        console.log("数据读取有异常")
    })

管道流

  1. pipe方法的底层实现了边读边写
  2. 非一次性全部读取
操作步骤
  1. 引入fs模块:let fs = require("fs")
  2. 创建可读流:let pipStreamR= fs.createReadStream(读取文件路径)
  3. 创建可写流:let pipStreamW = fs.createWriteStream(写入文件路径)
  4. 实现将一个文件的所有数据写入另一个文件中:pipStreamR.pipe(pipStreamW )
  5. 处理流的事件:
    pipStreamR.on("data",(res)=>{}):有数据可读时触发
    pipStreamR.on("end",()=>{}):读完成时触发
    pipStreamW.on("finish",()=>{}):写完成时触发

二、EventEmitter

  1. events模块只提供一个对象:events.EventEmitter(调用events.EventEmitter()方法可以获取EventEmitter类)。EventEmitter的核心就是事件触发与事件监听器功能的封装
  2. EventEmitter对象如果在实例化时发生错误,会触发error事件
  3. 要先注册后发送(即on方法在emit之前执行)
1. 使用步骤:
  1. 引入events模块:let events = require('events')
  2. 创建EventEmitter对象:let eventEmitter = new events.EventEmitter()
  3. 使用(注册事件、给事件绑定监听器、移除事件的监听器…)
2. EventEmitter对象方法
eventEmitter.on(事件名称,监听器(函数))
  1. 为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数。
  2. 当向eventEmitter对象发送事件时(调用emit方法绑定事件名称名称),会调用该事件的监听器(函数)
eventEmitter.emit(事件名称, [监听器1], [监听器2], [...])
  1. 按监听器的顺序执行执行每个监听器(按照实参顺序
  2. 如果事件有注册监听返回 true,否则返回 false。
  3. 如果只有一个实参,则按照注册顺序执行监听器
eventEmitter.addListener(事件名称,监听器(函数))

为指定事件添加一个监听器到监听器数组的尾部(即最后执行)

eventEmitter.once(事件名称,监听器(函数))

为指定事件注册一个单次监听器(该监听器只触发一次,触发完后移除)

eventEmitter.removeListener(事件名称,监听器名称(函数名称))

移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器

eventEmitter.removeAllListeners([事件名称])

移除所有事件的所有监听器(即没有参数);如果指定事件(即给定参数),则移除指定事件的所有监听器

eventEmitter.listeners(事件名称)

返回指定事件的监听数组(返回的是函数集合,可取每一个元素进行调用执行

3. EventEmitter类方法
events.emitter.listenerCount(eventName)

获取指定事件的监听器个数

4. 事件

在这里插入图片描述

三、ejs模板语法

什么是ejs
  1. EJS 是一套简单的模板语言,帮你利用普通的 JavaScript 代码生成 HTML 页面。EJS 只是普通的 JavaScript 代码而已。(可将js代码嵌入到html中且这些js代码可被解析成html)
  2. EJS是一个JavaScript模板库,用来从JSON数据中生成HTML字符串。

在这里插入图片描述

1. 使用步骤:
  1. 安装ejsnpm install ejs --save-dev
  2. 使用ejslet ejs = require("ejs")
  3. 使用:在js中通过ejs.render()/ejs.renderFile()方法可得到ejs模板的内容,并通过res.end()将其渲染到页面上去。
2. delimiter

可通过ejs.delimiter=""将默认的%替换成等号右边的字符。在使用时,需要将所有%当然不包括想要输出的%)替换成右边的字符(即右边字符和原本的%作用相同,用来解析js(不能右边字符和%混用,替换后只能用右边的字符)

3.include(path,data)
  1. 在一个ejs文件中引入另一个ejs文件,data为向目标ejs传送的数据。path为被引入的ejs文件目录
  2. 返回是一个字符串,需要用<%-%>/<%=%>将返回的内容解析,如果不加,则在页面无法解析返回的数据,且只能打印处include("...")
4. ejs渲染函数
render(template,data,options)

返回一个字符串,即将模板解析过的内容,可渲染到页面上。

参数详解
  • template:模板字符串(需要用转义字符引起来
  • data:给模板字符串传送的数据
  • options(一般不用):
    在这里插入图片描述
 ejs.delimiter = '~';//将默认的%设置为~ 在使用时,必须全部使用替换后的字符
    var html = ejs.render(`
      <~for(var i=0;i<num;i++){~>
       <h2><~=user.name~></h2>
      <h2><~=user.age~></h2>
  <~}~>`,{
   user:{
          name:"张园园",
        age:22
    },num:2
   })
    res.end(html)//html是解析后的html,可渲染到页面上

在这里插入图片描述

renderFile(path,data,options,callback)
  1. 没有返回值
  2. path直接写父文件夹/xxx.ejs即可。
参数详解
  • path:模板字符串所在文件(后缀为.ejs,如果在express中配置,后缀也可为html
  • data:向模板字符串传递的数据
  • callback:回调函数接收两个参数,一个为err,一个为strstr为解析后的html,可直接渲染到页面上
  ejs.renderFile("view/index.ejs", {
    student: data
 }, (err, str) => {
    console.log(str)
   res.end(str);//渲染到页面上
 });
4. ejs语法
语法 解释
<% 脚本标签,用于流程控制,无输出
<%_ 删除其前面的空格符
<%= 输出数据到模板(输出的为转义HTML标签)
<%- 输出非转义的数据到模板(所有数据都不转义(如果数据中有html标签,则不会将html标签解析成字符串,则是解析成html)
<%# 注释标签。不执行、不输出内容
<%% 输出字符串<%( eg:<%%22222%>输出模板字符串<%22222%>
%> 一般结束标签(<%str%>、<%= str %>、<%-str%>、<%#str%>、<%%str%>、<%_str%>
-%> 删除紧随其后的换行符
_%> 将结束标签后面的空格符删除
//服务端回调函数 .js
ejs.renderFile("view/index.ejs", {
        student: data//data为引入data.json外部模块的名称
     }, (err, str) => {
    res.end(str);//res为回调函数的res参数。将str渲染到页面上
     });

//login.ejs
<ul>
    <li>2</li>
    <li>2</li>
    <li>2</li>
    <li>2</li>
    <li>2</li>
    <li>2</li>
    <li>2</li>
    <li>2</li>
    <li>2</li>
    <li>2</li>
    <li>2</li>
    <li>2</li>
</ul>



//index.ejs
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <ul>
        <%for(let i=0;i<student.length;i++){%>
        <li><%=student[i].name%></li>
        <%}%>
    </ul> 
    <%
        var str = "<div></div>"
    %>
    <%#123%>
    <%%if(user.name)%>
    <%- str %>
    <%=str%>
    <%-include("./login.ejs")%>
</body>
</html>


//data.json

[
    {
        "name": "张三",
        "age": 18
    },
    {
        "name": "张三四",
        "age": 18
    },
    {
        "name": "李四",
        "age": 18
    },
    {
        "name": "王麻子",
        "age": 18
    },
    {
        "name":"<span>hello</span>"
    }
]

在这里插入图片描述

5. 在.ejs文件的javascript中获取从服务端传来的JSON数据
let jsonData = "<%-JSON.stringify(数据变量)%>"
JSON.parse(jsonData);//得到传来的json数据

注意:

  • 只能用单引号''或者反编译符将解析成字符串的数据的模板标签引起来。若用双引号"",会报错(Uncaught SyntaxError: Unexpected identifier
  • 应该用<%-%>将解析成字符串的数据包裹起来。否则会将json数据中的""进行转义。
发布了72 篇原创文章 · 获赞 72 · 访问量 6305

猜你喜欢

转载自blog.csdn.net/weixin_43314846/article/details/103301261
EJS