二.Node:全局对象,事件,异步特性

1.javaScript是单线程,所以是同步。Node通过事件循环(event loop)模拟异步环境

2.Node环境浏览器环境的本质区别是二进制数据的缓存

  • 虽然Node现在可以操作ES6的ArrayBuffer类型化数组。但是大部分很二进制有关的还是用Buffer类实现。
  • buffer是Node的一个全局对象,另一个全局对象是global本身。Node还能访问另一个全局变量process——Node应用和其环境桥梁

1.global和process对象

1.与浏览器中的不同Node中的全局变量只能在定义它的模块中使用。

2.process提供了Node应用和当前运行环境的信息。通过process可以操作标准I/O

3.标准流是用于应用环境之间沟通的通道

4.标准流由标准输入(stdin)、标准输出(stdout)、标准错误(stderr)组成。

  • 这些通道可以帮助Node应用控制台之间通信
  • process.stdin:stdin的可读流。
  • process.stdout:stdout的可写流。
  • process.stderr:stderr的可写流。

5.process的I/O函数继承自EventEmitter。它可以触发事件捕获事件处理数据

process.stdin.setEncoding(utf8);
//为了从process.stdin中读取数据,要设置流的编码,否则读的是二进制的buffer而不是字符串。

process.stdin.on('readable',()=>{
//监听readable事件,当有很多数据可以读取时,该事件会通知我们。

    var input=process.stdin.read();//读取数据
    if(input!==null){
        process.stdout.write(input);//数据打印到process.stdout
        var command=input.trim();
        if(command=='exit'){//监听到退出字符串时
            process.exit(0);//结束这个程序
       }
      }
    })

运行这个应用,所有敲出来的内容都会被立刻输出。如果输入exit程序就会立即结束。

2.缓冲器(buffer)、类型化数组、字符串

1.当将buffer转换成类型化数组时:

  • 缓冲器的内存会被复制一份,不是共享内存。
  • buffer内存被解释成数组,而不是字节数组。(new Buffer([1,2,3,4])会被转换成有4个元素的类型化数组[1,2,3,4],而不是一个元素的[0x1020304])

2.Node的buffer是存储于V8堆之外的原始二进制数据。

  • 一旦分配了存储空间就不能再修改空间大小。
  • buffer是读写文件的默认数据类型

3.创建新的Node buffer不会初始化其中的内容。而类型化数组会。

4.可以在填充buffer的内容时指定编码

5.如果在创建buffer时直接向函数传入一个字节数组或另一个缓冲器或一个字符串,那么Node会复     制参数内容用来创建新的buffer。

6.buffer可以转换成JSON或字符串。

let buf=new Buffer.from('This is my pretty example');
//<Buffer 54 68 69 73 20 69 73 20 6d 79 20 70 72 65 74 74 79 20 65 78 61 6d 70 6c 65>
let json=JSON.stringify(buf);
//{"type":"Buffer","data":[84,104,105,115,32,105,115,32,109,121,32,112,114,101,116,116,121,32,101,120,97,109,112,108,101]}
let buf2=new Buffer.from(JSON.parse(json).data);
console.log(buf2.toString());//This is my pretty example

7.StringDecoder也可以将buffer中的数据转化为字符串,而且结果可逆

  • 如果遇到一个不完整字符序列,StringDecoder会将它存到缓冲器中,直到序列变得完整再输出,而buffer.toString()则会直接输出导致乱码

8.以指定的偏移量(offset)来对buffer读写。

let buf=Buffer.alloc(4);
buf.writeUint8(0x63,0 );
buf.writeUint8(0x61,1);
buf.writeUint8(0x74,2);
buf.writeUint8(0x73,3);

console.log(buf);//<Buffer 63 61 74 73>
console.log(buf.toString());//cats

9.字节序是指数据被存储的格式

  • 最高位被存储在最低的内存地址上,为大端格式。
  • 最低位被存储在最低的内存地址上,为小端格式。

3.Node回调函数,异步事件处理

1.事件驱动架构:

  • 进程被调用。应用不会等待其完成。
  • 进程通过触发一个事件来表示其结束。
  • 该事件被添加到队列或事件循环中。
  • 所有依赖于该事件的函数都会针对它注册一个监听函数。
  • 当事件被取出和处理时,依赖该事件的函数会执行,同时系统会将事件相关数据发送给这些函数。

2.异步回调函数:

  • 最后一个参数是一个回调函数。
  • 错误发生时,创建一个Error对象并将其作为回调函数的第一个参数。
  • 如果没有错误,就调用回调函数callback(null,data)。
  • 回调函数必须在process.nextTick()中调用。从而确保进程不被阻塞。

3.为了确保回调是异步的,需要在process.nextTick()函数中调用它。

  • process.nextTick()可以确保在调用函数之前清除事件循环。
  • 这意味着在调用阻塞功能之前,所有的同步功能都已经被处理。

4.大多数情况下,Node是单线程。

  • Node的事件循环是单线程。
  • 但这不意味着后台没有多个线程在工作。(C++和libuv库)

3.1 EventEmitter

1.只要看见一个对象触发事件,或者一个事件被on函数捕获,那就是EventEmitter的功能。

2.EventEmitter激活了Node中的异步事件处理。

const eventEmitter=require('events').EventEmitter

let counter=0
const em=new eventEmitter()

setInterval(()=>{
    em.emit('timed',counter++)
},3000)

em.on('timed',(data)=>{
    console.log('timed'+data)
})
/*每3秒输出一个timed
timed0
timed1
timed2
......
*/

3.EventEmitter的功能是继承来的,所以要用Util对象来启用继承功能。

  • util.inherits(obj,EventEmitter)使一个构造函数继承另一个构造函数的原型方法。
  • util.inherits()还可以直接在构造函数中访问父构造函数。
  • util.inherits()还可以让让我们在任何类中继承Node的事件队列功能。

4.on是addListener的缩写。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值