资讯专栏INFORMATION COLUMN

node事件循环 EventEmitter 异步I/O Buffer缓冲区 模块

SexySix / 671人阅读

摘要:一个匿名函数,执行,事件全部完成,执行最后一句,程序执行完毕。这个事件的监听器为一个匿名函数,事件名称为,当秒以后被触发先对象发送一个事件触发了匿名函数即监听器,监听器被执行。

node.js事件循环

node.js单进程,单线程的程序
每一个api都支持回调
所有的事件机制都是设计模式中的

一共是23种设计模式 
http://design-patterns.readth...
一个对象发生改变的时候,将自动通知其他对象,其他对象将相应的做出反应。发生改变的对象为观察目标,被通知的对象为观察者。一个观察目标可以对应多个观察者,而这些观察者之间没有任何联系,可以根据需要增加观察者,使得系统更加容易扩展,依赖关系为一对多,又被称为模型-视图模式
事件驱动程序

web server接收到请求,将其关闭,进行处理,然后接着服务下一个web请求。
当请求完成以后,放回处理队列,当到达队列开头的时候,将其结果返回给用户
即非阻塞式I/O 事件驱动I/O
会有一个主循环来监听事件,当检测到事件以后,触发回调函数

代码
PS C:UsersmingmDesktop	est> node main.js
连接成功
数据接收成功
程序执行完毕
PS C:UsersmingmDesktop	est>
// 引入一个 events 模块
var events = require("events");
// 创建 eventEmitter对象
var eventEmitter = new events.EventEmitter();

// 创建connection事件的处理程序
var connectHandLer = function connected() {
    console.log("连接成功");

    // 触发 data_received 事件
    eventEmitter.emit("data_received");
};

// 绑定cinnection事件处理程序
eventEmitter.on("connection", connectHandLer);

// 绑定data_received事件,并完成处理程序的书写
eventEmitter.on(
        "data_received",
        function() {
            console.log("数据接收成功");
        }
    );

// 触发 connection 事件
eventEmitter.emit("connection");

console.log("程序执行完毕");

程序的执行过程,先完成各种绑定,触发connection事件以后,寻找绑定的处理程序,为connected(),然后,执行一半,又被触发,data_received事件。寻找绑定的处理程序。一个匿名函数,执行,事件全部完成,执行最后一句,程序执行完毕。
多用户执行的情况下,触发事件以后,若处理程序正被其他用户占用,排队,直到前方全部处理完成以后,接着该用户使用处理程序进行处理。

EventEmitter

node所有的异步I/O操作在完成的时候都会发送到一个事件到达事件队列。node里的对象能够分发事件
产生的事件的对象都是events.EventEmitter的实例

EventEmitter类

events模块提供一个对象,它是对事件的触发和事件的监听的封装

PS C:UsersmingmDesktop	est> node main.js
事件触发
PS C:UsersmingmDesktop	est>

过五秒后响应

// event.js文件
var EventEmitter = require("events").EventEmitter;
var event = new EventEmitter();    // 创建一个event对象
event.on("some_event", function(){console.log("事件触发");});
setTimeout(function(){event.emit("some_event");}, 5000);

大概解释一下这段代码
前两句很简单,后两句说一下,event的对象注册了一个事件的监听器。这个事件的监听器为一个匿名函数,事件名称为some_event,当5000秒以后被触发先对象event发送一个事件some_event触发了匿名函数即监听器,监听器被执行。
其中EventEmitter的每个事件由一个事件名和若干参数组成,对于一个事件能有若干的监听器,当事件触发的时候,监听器会被依次调用,事件参数作为回调函数的参数进行传递,需要注意的是,监听器会被依次调用

error事件

error是一个多带带列出来的事件,一般要为其绑定一个监听器,因为node如果抛出error,若没有监听器执行,将会直接退出执行,并返回错误

Buffer缓冲区

处理TCP或者文件流的时候,需要用到二进制的数据,定义了一个Buffer类,该类用于专门存放二进制数据的缓冲区

Buffer与字符编码
const buf = Buffer.from("ming", "ascii");    // 声明一个只读的变量

console.log(buf.toString("hex"));

console.log(buf.toString("utf-8"));
PS C:UsersmingmDesktop	est> node main.js
6d696e67
ming
PS C:UsersmingmDesktop	est>
创建一个buffer类,并完成读取写入
PS C:UsersmingmDesktop	est> node main.js
23456789:;<=>?@ABCDEFGHIJK
23456789:;<=>?@ABCDEFGHIJK
PS C:UsersmingmDesktop	est>
buf = Buffer.alloc(26);
for(var i = 0; i < 26; i++){
    buf[i] = 50 + i;
};
console.log(buf.toString("ascii"));
console.log(buf.toString("utf8"));
将buffer转换为jsoon
PS C:UsersmingmDesktop	est> node main.js
{"type":"Buffer","data":[1,2,3,4,5]}
PS C:UsersmingmDesktop	est>
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);

console.log(json);
将JSON转换为Buffer 一个转换方法JSON.parse
> JSON.parse("{"1": 3, "2": [4, 5, 6]}", function (k, v) {
...     console.log(k); // 输出当前的属性名,从而得知遍历顺序是从内向外的,
...     console.log("----------");              // 最后一个属性名会是个空字符串。
...     console.log(v);
... });
1
----------
3
0
----------
4
1
----------
5
2
----------
6
2
----------
[ <3 empty items> ]

----------
{}
undefined
>
开始转换
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);

console.log(json);


const copy = JSON.parse(    // 调用JSON.parse函数,将字符串转换为对象,后一个参数为转换的函数,转换的时候将会调用
        json,
        (key, value) => {    // 此为es6的语法,一个匿名函数
            console.log(value, "----", !!value, "----", value.type, "-----", value.data);
            return value && value.type === "Buffer" ? Buffer.from(value.data): value;    // 只留下最后一个进行转换,前面的转换全部被覆盖
        }
    )

// 输出: 
console.log(copy);
PS C:UsersmingmDesktop	est> node main.js
{"type":"Buffer","data":[1,2,3,4,5]}
Buffer ---- true ---- undefined ----- undefined
1 "----" true "----" undefined "-----" undefined
2 "----" true "----" undefined "-----" undefined
3 "----" true "----" undefined "-----" undefined
4 "----" true "----" undefined "-----" undefined
5 "----" true "----" undefined "-----" undefined
[ 1, 2, 3, 4, 5 ] "----" true "----" undefined "-----" undefined
{ type: "Buffer", data: [ 1, 2, 3, 4, 5 ] } "----" true "----" "Buffer" "-----" [ 1, 2, 3, 4, 5 ]

PS C:UsersmingmDesktop	est>
Buffer的合并
var buffer1 = Buffer.from("222");
var buffer2 = Buffer.from("3333");
var buffer3 = Buffer.concat([buffer1, buffer2]);
console.log(buffer3.toString());
Stream流

流为一个抽象的接口,

从流中读取数据
PS C:UsersmingmDesktop	est> node main.js
end!
33333333333333333333333333
PS C:UsersmingmDesktop	est>
var fs = require("fs");
var data = "";

// 创建可读流
var readerStream = fs.createReadStream("input.txt");

// 设置编码为 utf8
readerStream.setEncoding("UTF8");

// 处理流事件 data事件
readerStream.on("data", (chunk) => {data += chunk;});    // 遇到数据读取,将读取到的内容赋值给data

// 处理流事件 end事件
readerStream.on("end", () => {console.log(data);});    // 将读取到的保存到内存中的数据打印出来

// 处理事件 error
readerStream.on("error", (err) => {console.log(err.stack);});    // 处理error事件,将错误输出,避免程序的运行中断

console.log("end!");
写入流
PS C:UsersmingmDesktop	est> node main.js
程序执行完毕
写入完成
PS C:UsersmingmDesktop	est>
var fs = require("fs");
var data = "这是一段示例";

// 创建一个可以写入的流,写入到文件output.txt中
var writerStream = fs.createWriteStream("output.txt");

// 使用 utf8 编码写入数据
writerStream.write(data, "UTF8");

// 标记文件末尾
writerStream.end();

// 处理流事件 --> data, end, add error
writerStream.on("finish", () => {console.log("写入完成");});

writerStream.on("error", () => {console.log(err.stack);});

console.log("程序执行完毕");

管道流

把两个文件之间建立流,让一个文件的数据流向另外一个文件

PS C:UsersmingmDesktop	est> node main.js
程序执行完毕
PS C:UsersmingmDesktop	est>
var fs = require("fs");

// 创建一个可读流
var readerStream = fs.createReadStream("input.txt");

// 创建一个可写流
var writerStream = fs.createWriteStream("output.txt");

// 管道读写操作
// 将两个流通过管道连接起来
readerStream.pipe(writerStream);

console.log("程序执行完毕");

这里需要注意的是,由于流的影响,导致在操作的时候,会覆盖掉要写入文件的内容,原先的内容会被覆盖

链式流
PS C:UsersmingmDesktop	est> node main.js
文件压缩完成
PS C:UsersmingmDesktop	est>
var fs = require("fs");
var zlib = require("zlib");

// 压缩 input.txt文件为 input.txt.gz
fs.createReadStream("input.txt")    // 创建一个可读流
    .pipe(zlib.createGzip())        // 将创建的可写流和压缩流连接
    .pipe(fs.createWriteStream("input.txt.gz"));    // 在创建可写流,将三个流连接到一起

console.log("文件压缩完成");
内容未被覆盖的写入
var fs = require("fs");
var read = fs.createReadStream("output.txt");
var write = fs.createWriteStream("input.txt");
read.pipe(write);
console.log("执行完毕");

具体详细,请查文档
https://nodejs.org/api/fs.htm...
https://nodejs.org/api/fs.htm...
文档写的很详细,后面的参数为一个对象,通过对象即可进行修改

模块

模块之前已经阐述过一部分,这里阐述服务器端的模块

服务器端的模块

node中自带了一个http模块,在代码中请求他,并将返回值赋值给本地变量。即本地变量变成了一个拥有所有http模块所提供的公共方法的对象。
node中有四个模块,(原生模块和三种文件模块)

从文件模块的缓存中添加

原生模块和文件模块优先级不同,都会优先从文件模块的缓存中加载以及存在的模块

从原生模块加载

原生模块的优先级低于文件模块缓存的优先级。原生模块也有缓存区

从文件加载

这个上一篇以及阐述完成,不在阐述

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96281.html

相关文章

  • Node.js学习总结

    摘要:表示当前正在执行的脚本的文件名。默认编码为模式为,为回调函数,回调函数只包含错误信息参数,在写入失败时返回。参数使用说明如下通过方法返回的文件描述符。 Node.js回调 Node.js异步编程的直接体现就是回调。 阻塞代码: const fs = require(fs); let data = fs.readFileSync(input.txt); console.log(data...

    kamushin233 评论0 收藏0
  • 认识node核心模块--从Buffer、Stream到fs

    摘要:端输入数据到端,对就是输入流,得到的对象就是可读流对就是输出端得到的对象是可写流。在中,这四种流都是的实例,它们都有事件,可读流具有监听数据到来的事件等,可写流则具有监听数据已传给低层系统的事件等,和都同时实现了和的事件和接口。 原文地址在我的博客 node中的Buffer和Stream会给刚接触Node的前端工程师们带来困惑,原因是前端并没有类似概念(or 有我们也没意识到)。然而,...

    TANKING 评论0 收藏0
  • Node.js 中度体验

    摘要:创建简单应用使用指令来载入模块创建服务器使用方法创建服务器,并使用方法绑定端口。全局安装将安装包放在下。的核心就是事件触发与事件监听器功能的封装。通常我们用于从一个流中获取数据并将数据传递到另外一个流中。压缩文件为文件压缩完成。 创建简单应用 使用 require 指令来载入 http 模块 var http = require(http); 创建服务器 使用 http.create...

    CastlePeaK 评论0 收藏0
  • Node_深入浅出Node

    摘要:简介项目命名为就是一个服务器单纯开发一个服务器的想法,变成构建网络应用的一个基本框架发展为一个强制不共享任何资源的单线程,单进程系统。单线程弱点无法利用多核错误会引起整个应用退出,应用的健壮性大量计算占用导致无法继续调用异步。 NodeJs简介 Ryan Dahl项目命名为:web.js 就是一个Web服务器.单纯开发一个Web服务器的想法,变成构建网络应用的一个基本框架.Node发展...

    shinezejian 评论0 收藏0
  • Node.js设计模式》高级异步准则

    摘要:这使我们的知道什么时候原始模块被初始化,在初始化后执行预初始化队列的操作,之后清空预初始化队列,再调用作为参数的回调函数,以下为具体步骤把赋值给,表示预初始化已经完成了。 本系列文章为《Node.js Design Patterns Second Edition》的原文翻译和读书笔记,在GitHub连载更新,同步翻译版链接。 欢迎关注我的专栏,之后的博文将在专栏同步: Encount...

    wfc_666 评论0 收藏0

发表评论

0条评论

SexySix

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<