node基础详解

2022-11-24 0 547

此栏最终目标

认知Buffer认知Stream认知Eventsnode中的自上而下第一类

科学知识关键点

认知BufferArrayBuffer通用型的、一般来说宽度的原初十进制统计数据头文件,不能间接操作方式,而要透过类别字符串第一类(TypedArray)操作方式,将头文件中的Luzy为某一的文件格式。能将其认知为几块缓存,具体文本存甚么须要其它的新闻稿
const buffer = new rrayBuffer(8) console.log(buffer) // ArrayBuffer { [Uint8Contents]:<00 00 00 00 00 00 00 00>,[byteLength]:8 } const int16Buffer = new Int16Array(buffer) console.log(int16Buffer) // Int16Array(4) [0,0,0,0]

2. Unit8Array

则表示两个8位的无记号auth字符串,建立的这时候文本被调用为0
const unit8 = new Uint8Array(2) unit8[0] = 42 console.log(unint8[0]) // 42 console.log(unit8.length) // 2console.log(unit8.BYTES_PER_ELEMENT) // 1 const arr = new Uint8Array([21,31]) console.log(arr[1]) // 31

3. ArrayBuffer与TypedArray的关系

TypedArray:Uint8Array, Int32Array, Int16Array

ArrayBuffer: 本身是两个0、1存放在一行里的集合

关系:使用TypedArray划分ArrayBuffer中的十进制字节,

4. node中使用Buffer

Buffer实现了Uint8Array的api

Buffer的实例 => auth字符串 (用于则表示编码字符的序列 UTF-8 Base64 十六进制)

Buffer的大小是一般来说的,在建立时就确定了,无法调整
const buf1 = Buffer.alloc(10) // 建立两个宽度为10 填充为0的Buffer console.log(buf1) // <Buffer 00 00 00 00 00 00 00 00 00 00> const buf2 = Buffer.alloc(10,1) // 建立两个宽度为10 填充为1的Bufferconsole.log(buf2) // <Buffer 01 01 01 01 01 01 01 01 01 01 > const buf3 = Buffer.allocUnsafe(10) // 建立两个宽度为10, 速度比alloc快 但是建立的头文件里可能有旧统计数据 console.log(buf3) // <Buffer d8 0b 01 06 00 00 00 00 08 da> const buf = Buffer.from(hellow world, ascii) // 参数1:生成文本 参数2:文本的编码方式 console.log(but) // <Buffer 68 65 6c 6f 20 77 6f 72 6c 64>console.log(buf.toString(base64)) // …base64编码的字符串

认知Streamshell透过管道连接各个部分,输入和输出的规范是文本流

nodejs内置的Stream模块实现了类似的功能,各个部分之间透过pipe()连接

流中的统计数据默认情况下都是Buffer类别。产生的统计数据一放入流中,便转成Buffer被消耗;写入的统计数据在传给底层写逻辑时,也被转成Buffer类别。Stream.Readable 可读

建立可读流时须要继承Readable并实现_read方法

_read方法是从底层系统读取具体文本统计数据的逻辑,即生产统计数据的逻辑。 在_read方法中,透过调用push(data)将统计数据放入可读流中供下游消耗。 在_read方法中,能同步调用push(data),也能异步调用。 当全部统计数据都生产出来后,必须调用push(null)来结束可读流。 流一旦结束,便不能再调用push(data)添加统计数据。
const Readable = require(stream).Readable class ToReadable extends Readable { constructor(){ super() this.iterator = iterator } _read(){ const res = this.iterator.next() if(res.done){ return this.push(null) } setTimeout(()=>{ this.push(res.value) },0) } } const iterator = function(limit){ return { next: function(){ if(limit–){ return {done:false,value:limit+Math.random()} } return { done: true } } } }(10) const readable = new ToReadable(iterator) readable.on(data, data=>{process.stdout.write(data)}) readaable.on(end, ()=>{process.stdout.write(DONE)})

2. Stream.Writeable 可写

Readable透过继承的方式去建立一类可读流,Writeable也适用于建立一类可写流,只是须要实现的是write(data, enc, next)方法,而不是read()方法

上游透过调用writable.write(data)将统计数据写入可写流中。write()方法会调用_write()将data写入底层。在_write中,当统计数据成功写入底层后,必须调用next(err)告诉流开始处理下两个统计数据。next的调用既能是同步的,也能是异步的。上游必须调用writable.end(data)来结束可写流,data是可选的。此后,不能再调用write新增统计数据。在end方法调用后,当所有底层的写操作方式均完成时,会触发finish事件。
const Writable = require(stream).Writable const writable = Writable() // 实现`_write`方法 // 这是将统计数据写入底层的逻辑 writable._write = function (data, enc, next) { // 将流中的统计数据写入底层 process.stdout.write(data.toString().toUpperCase()) // 写入完成时,调用`next()`方法通知流传入下两个统计数据 process.nextTick(next) } // 所有统计数据均已写入底层writable.on(finish, () => process.stdout.write(DONE)) // 将两个统计数据写入流中 writable.write(a + \n) writable.write(b + \n) writable.write(c + \n) // 再无统计数据写入流时,须要调用`end`方法 writable.end()

3. Stream.Duplex 可读可写

Duplex实际上就是继承了Readable和Writable的一类流。 所以,两个Duplex第一类既可当成可读流来使用(须要实现read方法),也可当成可写流来使用(须要实现write方法)。

var Duplex = require(stream).Duplex var duplex = Duplex() // 可读端底层读取逻辑 duplex._read = function () { this._readNum = this._readNum || 0 if (this._readNum > 1) { this.push(null) } else { this.push( + (this._readNum++)) } } // 可写端底层写逻辑 duplex._write = function (buf, enc, next) { // a, b process.stdout.write(_write + buf.toString() + \n) next() } // 0, 1 duplex.on(data, data => console.log(ondata, data.toString())) duplex.write(a) duplex.write(b) duplex.write(x) duplex.end()

4. Stream.Transform 可读可写可变换

Duplex的例子中,可读流中的统计数据(0, 1)与可写流中的统计数据(’a’, ‘b’)是隔离开的,但在Transform中可写端写入的统计数据经变换后会自动添加到可读端。 Tranform继承自Duplex,并已经实现了read和write方法,同时要求用户实现两个_transform方法。

const Transform = require(stream).Transform class Rotate extends Transform { constructor(n) { super() // 将字母移动`n`个位置 this.offset = (n || 13) % 26 } // 将可写端写入的统计数据变换后添加到可读端 _transform(buf, enc, next) { var res = buf.toString().split().map(c => { var code = c.charCodeAt(0) if (c >= a && c <= z) { code += this.offset if (code > z.charCodeAt(0)) { code -= 26 } } else if (c >= A && c <= Z) { code += this.offset if (code > Z.charCodeAt(0)) { code -= 26 } } return String.fromCharCode(code) }).join() // 调用push方法将变换后的统计数据添加到可读端 this.push(res) // 调用next方法准备处理下两个 next() } } var transform = new Rotate(3) transform.on(data, data => process.stdout.write(data)) transform.write(hello, ) transform.write(world!) transform.end()

认知Eventsevents模块是node的核心模块之一,几乎所有常用的node模块都继承了events模块,比如http、fs等。

注册事件监听器前,事件先触发,则该事件会间接被忽略单个事件监听器
// 事件触发时,事件监听器按照注册的顺序执行var EventEmitter = require(events); class Man extends EventEmitter {} var man = new Man(); man.on(wakeup, function(){ console.log(man has woken up); }); man.emit(wakeup); // man has woken up

2. 同个事件 多个事件监听器

var EventEmitter = require(events); class Man extends EventEmitter {} var man = new Man(); man.on(wakeup, function(){ console.log(man has woken up); }); man.on(wakeup, function(){ console.log(man has woken up again); }); man.emit(wakeup);

3. 只运行一次的事件监听器

var EventEmitter = require(events); class Man extends EventEmitter {} var man = new Man(); man.on(wakeup, function(){ console.log(man has woken up); }); man.once(wakeup, function(){ console.log(man has woken up again); }); man.emit(wakeup); man.emit(wakeup); // 输出如下: // man has woken up // man has woken up again// man has woken up

4. 移除事件监听

var EventEmitter = require(events); function wakeup(){ console.log(man has woken up); } class Man extends EventEmitter {} var man = new Man(); man.on(wakeup, wakeup); man.emit(wakeup); man.removeListener(wakeup, wakeup); man.emit(wakeup); // 输出如下: // man has woken up

node中的自上而下第一类Node.js 中的自上而下第一类是 global,所有自上而下变量(除了 global 本身以外)都是 global 第一类的属性。

global 最根本的作用是作为自上而下变量的宿主

自上而下变量的定义:在最外层定义的变量;自上而下第一类的属性;隐式定义的变量(未定义间接赋值的变量)。
// node中的this其实是module.exports console.log(this); // {} module.exports.foo = 5; console.log(this); // { foo:5 }
自上而下变量__filename

__filename 则表示当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同。 如果在模块中,返回的值是模块文件的路径。

2. 自上而下变量__dirname

__dirname 则表示当前执行脚本所在的目录。

3. 自上而下方法 setTimeout(cb, ms), clearTimeout, setInterval, clearInterval, console,

4. 自上而下变量 process

用于描述当前Node.js 进程状态的第一类,提供了两个与操作方式系统的简单接口。

// process 对象的一些最常用的成员方法 // exit 当进程准备退出时触发。 process.on(exit, function(code) {}) // beforeExit 当 node 清空事件循环,并且没有其它安排时触发这个事件。通常来说,当没有进程安排时 node 退出,但是 ‘beforeExit’ 的监听器能异步调用,这样 node 就会继续执行。 process.on(beforeExit, function(code) {}) // uncaughtException 当两个异常冒泡回到事件循环,触发这个事件。如果给异常添加了监视器,默认的操作方式(打印堆栈跟踪信息并退出)就不会发生。 process.on(uncaughtException, function(code) {}) // Signal 当进程接收到信号时就触发。信号列表详见标准的 POSIX 信号名,如 SIGINT、SIGUSR1 等。 process.on(Signal, function(code) {}) // 输出到终端 process.stdout.write(“Hello World!” + “\n”); // 透过参数读取 process.argv.forEach(function(val, index, array) { co // 平台信息 console.log(process.platform);

补充

1字节(byte)= 8位(bit)js中Number 64位 => 8bytenode中目前支持的字符编码 [ 7位的ascii统计数据 | 多字节编码的Unicode字符.html | base64 ]退出时的状态码Uncaught Fatal Exception 有未捕获异常,并且没有被域或 uncaughtException 处理函数处理。

3 Internal JavaScript Parse Error JavaScript的源码启动 Node 进程时引起解析错误。非常罕见,仅会在开发 Node 时才会有。

4 Internal JavaScript Evaluation Failure JavaScript 的源码启动 Node 进程,评估时返回函数失败。非常罕见,仅会在开发 Node 时才会有。

5 Fatal Error V8 里致命的不可恢复的错误。通常会打印到 stderr ,文本为: FATAL ERROR

6 Non-function Internal Exception Handler 未捕获异常,内部异常处理函数不知为何设置为on-function,并且不能被调用。

7 Internal Exception Handler Run-Time Failure 未捕获的异常, 并且异常处理函数处理时自己抛出了异常。例如,如果 process.on(‘uncaughtException’) 或 domain.on(‘error’) 抛出了异常。

9 Invalid Argument 可能是给了未知的参数,或者给的参数没有值。

10 Internal JavaScript Run-Time Failure JavaScript的源码启动 Node 进程时抛出错误,非常罕见,仅会在开发 Node 时才会有。

12 Invalid Debug Argument 设置了参数–debug 和/或 –debug-brk,但是选择了错误端口。

node基础详解
下一篇: Node简介

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务