当前位置:   article > 正文

nodejs api学习

nodejs api

1.Assert

用于测试数据,比较数据是否相等

1.1 assert(value[, message])

第一个参数是值,第二个参数是异常时抛出的异常信息,第二个参数可不写,不写就是系统默认的错误信息

例子1:

  1. var assert = require("assert")
  2. assert(false,"第一个值为false时以我为错误信息抛出");

终端抛出:

  1. node:assert:400
  2. throw err;
  3. ^
  4. AssertionError [ERR_ASSERTION]: 第一个值为false时以我为错误信息抛出
  5. at Object.<anonymous> (F:\nodeDemo\16.assert.js:7:1)
  6. at Module._compile (node:internal/modules/cjs/loader:1126:14)
  7. at Object.Module._extensions..js (node:internal/modules/cjs/loader:1180:10)
  8. at Module.load (node:internal/modules/cjs/loader:1004:32)
  9. at Function.Module._load (node:internal/modules/cjs/loader:839:12)
  10. at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
  11. at node:internal/main/run_main_module:17:47 {
  12. generatedMessage: false,
  13. code: 'ERR_ASSERTION',
  14. actual: false,
  15. expected: true,
  16. operator: '=='
  17. }

把值改成true时,执行后面的代码

1.2 assert.ok(value[, message])

用法与assert(value[, message])一样

1.3 assert.equal(actual, expected[, message])

用于测试预期值与实际值是否相等,如果相等则断言通过,否则抛出message,相等于==

例子:

  1. var assert = require("assert")
  2. var a = 1+1
  3. assert.deepEqual(a,1,'值不相等')

1.4 assert.deepEqual(actual, expected[, message])

用于测试预期值与实际值是否相等,相当于==

equal的区别,deepEqual比较的是对象的属性值

  1. const obj={a:1};
  2. const obj2={a:1};
  3. assert.equal(obj,obj2,'equal 不等');//false
  4. assert.deepEqual(obj,obj2,'deepEqual 不等')//true

1.5 assert.deepStrictEqual(actual, expected[, message])

用于测试预期值与实际值是否相等,相当于===

1.6 assert.strictEqual(actual, expected[, message])

用于测试预期值与实际值是否相等,相当于===

1.7  assert.notEqual(actual, expected[, message])

2.Buffer

创建Buffer对象

2.1 Buffer.from()

        支持String、Array、ArrayBuffer、Object、buffer五种类型

--Buffer.from(String [,encoding]);

--Buffer.from(Array);

--Buffer.from(object[, offsetOrEncoding[, length]]);

2.2 Buffer.alloc(size[, fill[, encoding]])

2.3 Buffer.allocUnsafe()

2.4 Buffer.allocUnsafeSlow()

Buffer对象的属性和方法

2.5 Buffer.concat(list[, totalLength])

这是一个拼接Buffer的静态方法,参数list是所有拼接的Buffer对象的列表,totalLength是指定拼接成新的Buffer对象的长度,如果长度不够则会忽略后面数据

2.6 Buffer.isBuffer(obj)

这是一个Buffer静态方法,用来判断对选是否是一个Buffer对象。

2.7 Buffer.keys()

这是一个Buffer对象方法(公有方法),用来获取Buffer对象的key迭代器

2.8 buf.subarray(start,end)

subarray获取Buffer对象中的指定片段,与字符串拼接时会默认调用toString方法

string_decoder可以解决拼接时乱码

3.child_process

child_process模块用于新建子进程,子进程的运行结果储存在系统缓存之中(最大200KB),等到子进程运行结束以后,主进程再用回调函数读取子进程的运行结果。

3.1 child_process.exec(command[, options][, callback])

执行的是非node程序,是一个shell命令,执行结果以回调的形式返回。

3.2 child_process.execFile(file[, args][, options][, callback])

执行的是非node程序,是一个可执行文件或应用,执行结果以回调的形式返回

3.3 child_process.spawn(command[, args][, options])

执行的是非node程序,是一个shell命令,不需要获取执行结果,执行结果以流的形式返回。

3.4 child_process.fork(modulePath[, args][, options])

执行的是node程序,是一个.js文件,不需要获取执行结果,执行结果以流的形式返回,fork出来的进程一定是node进程。

子进程与父进程相互通信

在子进程中:

通过process.on('message')和process.send()的机制来接收和发送消息。

在父进程中:

通过child.on('message')和process.send()的机制来接收和发送消息。

4.cluster

4.1 isMaster,isWorker

区分时主进程还是工作进程

4.2 fork()

主进程中创建一个工作进程

4.3 kill()

终止工作进程

5. copyto 加密解密

  1. const crypto = require('crypto');
  2. function encrypto(key,data) { // 加密函数
  3. //key : 公钥 data:需要加密的数据,buffer格式
  4. return crypto.publicEncrypt(key,Buffer.from(data));
  5. }
  6. function decrypto(key,encrypted) { //解密函数
  7. //key : 私钥 encrypted: 解密的数据 , buffer格式
  8. return crypto.privateDecrypt(key,encrypted)
  9. }
  10. const str = '我真帅'//需要加密的
  11. const cryptoed = encrypto(public_key,str) //公钥加密
  12. const decryptoed = decrypto(private_key,cryptoed) //私钥解密

6.event

一个对象通过这个模块,向另一个对象传递消息

eventEmitter.on() 用于注册监听器

eventEmitter.emit() 用于触发事件

eventEmitter.once() 只触发一次

自定义的类或者对象都是没有实现或继承 Events 模块的,想要使用 Events 模块就需要先导入该模块。

类的继承event

  1. const event = require('events')
  2. class People extends event {
  3. constructor(name) {
  4. super()
  5. this.name = name
  6. this.on('eat', this.eat)
  7. }
  8. eat() {
  9. console.log(`${this.name} eat `);
  10. this.emit('age')
  11. }
  12. }
  13. module.exports = People

使用:

  1. const PeopleEvent = require('./peopleevent ')
  2. const tom = new PeopleEvent('tom')
  3. tom.on('age', () => {
  4. console.log(`${tom.name}'age is 18 `);
  5. })
  6. tom.emit('eat')

输出:

tom eat 
tom'age is 18 

还可以使用utilinherits方法继承(这种时过时的)

  1. const eventEmitter = require('events').EventEmitter
  2. const util = require('util')
  3. const people = function People(name) {
  4. this.name = name
  5. this.on('eat', eat)
  6. function eat() {
  7. console.log(`${this.name} eat `);
  8. this.emit('age')
  9. }
  10. }
  11. util.inherits(people, eventEmitter)
  12. module.exports = people;

使用:

  1. const People = require('./60.event')
  2. const tom = new People('Tom')
  3. tom.on('age', () => {
  4. console.log(`${tom.name}'age is 18 `);
  5. })
  6. tom.emit('eat')

输出时同样的 

tom eat 
tom'age is 18 

需要先注册在发布

7.fs

fs.readFileSync(fileName, "utf8");

        用于同步读取文件,返回一个字符串

        第一个参数是文件路径,第二个参数是文本文件编码默认为utf8

fs.writeFileSync(fileName, str, 'utf8');

        同步写入文件

        它的第一个参数是文件路径,第二个参数是写入文件的字符串,第三个参数是文件编码,默认为utf8

fs.exists(path, callback)

        判断给定路径是否存在,然后不管结果如何,都会调用回调函数

        fs.exists('/path/to/file', function (exists) {}

        exists是一个布尔值

        不要在open方法之前调用exists方法,open方法本身就能检查文件是否存在

fs.readFile(path[,options],callback) 

        用于异步读取文件

  1. let fs = require('fs');
  2. fs.readFile('example_log.txt', function (err, logData) {
  3. if (err) throw err;
  4. let text = logData.toString();
  5. });

fs.writeFile(file,data[,options],callback)

        用于异步写入文件

fs.stat检测文件还是目录/文件大小等

fs.mkdir创建目录

        mkdir接受三个参数,第一个是目录名,第二个是权限值,第三个是回调函数

        0777 表示可读可写可执行

        0666 表示可读可写

  1. let fs = require('fs');
  2. fs.mkdir('./helloDir',0777, function (err) {
  3. if (err) throw err;
  4. });

fs.appendfile 追加文件

fs.readdir读取目录

fs.rename

fs.rmdir删除目录  注意:目录下必须为空,才删除

fs.unlink 删除文件

8.module

require() 引入模块

module.exports 导出模块或值

Node为每个模块提供一个exports变量,指向module.exports。这等同在每个模块头部,有一行这样的命令

let exports = module.exports;
不能直接将exports变量指向一个值,因为这样等于切断了exports与module.exports的联系

内置的require命令用于加载模块文件

require命令用于加载文件,后缀名默认为.js

let foo = require('foo'); // 等同于 let foo = require('foo.js');

根据参数的不同格式,require命令去不同路径寻找模块文件:    

  1. 如果参数字符串以“/”开头,则表示加载的是一个位于绝对路径的模块文件。比如,require('/home/marco/foo.js')将加载/home/marco/foo.js
  2. 如果参数字符串以“./”开头,则表示加载的是一个位于相对路径(跟当前执行脚本的位置相比)的模块文件。比如,require('./circle')将加载当前脚本同一目录的circle.js
  3. 如果参数字符串不以“./“或”/“开头,则表示加载的是一个默认提供的核心模块(位于Node的系统安装目录中),或者一个位于各级node_modules目录的已安装模块(全局安装或局部安装)。
  4. 如果参数字符串不以“./“或”/“开头,而且是一个路径,比如require('example-module/path/to/file'),则将先找到example-module的位置,然后再以它为参数,找到后续路径
  5. 如果指定的模块文件没有发现,Node会尝试为文件名添加.js、.json、.node后,再去搜索。.js件会以文本格式的JavaScript脚本文件解析,.json文件会以JSON格式的文本文件解析,.node文件会以编译后的二进制文件解析。
  6. 如果想得到require命令加载的确切文件名,使用require.resolve()方法。

9.net

net.Server 创建服务器

1) 创建Server:var server = net.Server();
2) 监听已有的连接:server.listen(端口号,ip);
3) 监听事件使用on:
事件有: listening:当服务绑定后触发
connection:当一个新的connection(连接)建立的时候触发,有参数socket
close: 当server关闭的时候触发,注意要等到所有的连接都结束之后才触发
error: 当错误出现的时候触发

4) 方法:
listen:监听已有的连接
close:关闭连接
address:返回绑定的地址,只有在listening事件被触发的时候菜可以调用该事件,不然返回的是一个空对象

net.socket 可以被用户创建并直接与server通信,通过[net.createConnection()][]返回的

1) 创建一个连接:net.connect(端口号,ip);
2) 监听事件使用on:
事件有: connect:当一个socket连接成功建立的时候触发该事件
data:当接收到数据的时候触发该事件,数据编码由 socket.setEncoding() 设置
end: 关闭连接
timeout:连接超时触发
error:
3) 方法:
connect(端口,IP):创建连接
write(内容,编码格式-默认UTF8):在socket上发送数据
setTimeout():设置超时时长

4) 属性:
localPort:用数字表示本地端口。例如80或21
localAddress:返回操作系统报告的 socket 的地址、地址族和端口。返回的对象有三个属性,例如: { port: 12346, family: ‘IPv4’, address: ‘127.0.0.1’ }
remotePort:用数字表示远程端口
remoteAddress:用字符串表示远程IP地址

10.path

path.basename(path[, ext])  返回文件名字,添加第二个参数去掉文件后缀

path.dirname() 返回父路径

path.extname() 方法返回 path 的扩展名

path.format() 方法会从一个对象返回一个路径字符串

path.isAbsolute() 方法会判定 path 是否为一个绝对路径

path.join() 方法使用平台特定的分隔符把全部给定的 path 片段连接到一起,并规范化生成的路径

path.parse() 方法返回一个对象,对象的属性表示 path 的元素

  1. path.parse('/home/user/dir/file.txt');
  2. // 返回:
  3. // { root: '/',
  4. // dir: '/home/user/dir',
  5. // base: 'file.txt',
  6. // ext: '.txt',
  7. // name: 'file' }

path.relative() 方法返回从 from 到 to 的相对路径 

path.resolve() 方法会把一个路径或路径片段的序列解析为一个绝对路径

给定的路径的序列是从右往左被处理的,后面每个 path 被依次解析,直到构造完成一个绝对路径。 例如,给定的路径片段的序列为:/foo/barbaz,则调用 path.resolve('/foo', '/bar', 'baz') 会返回 /bar/baz

11.querystring

querystring.escape(str) 对给定的 str 进行 URL 编码。

querystring.parse(str[, sep[, eq[, options]]]) 该方法会把一个 URL 查询字符串 str 解析成一个键值对的集合

querystring.stringify(obj[, sep[, eq[, options]]]) 该方法通过遍历给定的 obj 对象的自身属性,生成 URL 查询字符串

  1. querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' });
  2. // 返回 'foo=bar&baz=qux&baz=quux&corge='

12 readline

基本用法:

  1. //引入readline模块
  2. const readline = require('readline');
  3. //创建readline接口实例
  4. let r1 = readline.createInterface({
  5. input:process.stdin,
  6. output:process.stdout
  7. });
  8. //使用question方法
  9. r1.question('你想吃什么?',function (anwser){
  10. console.log(`我想吃${anwser}`);
  11. //添加close事件,不然不会结束
  12. r1.close();
  13. });
  14. //close事件监听
  15. r1.on('close',function (){
  16. //结束程序
  17. process.exit(0);
  18. });

readline.Interface 类的实例是使用 readline.createInterface() 方法构造的

当 'close' 事件被触发时,readline.Interface 实例会被结束

line事件:每当 input 流接收到接收行结束符(\n\r 或 \r\n)时触发 'line' 事件。 通常发生在用户按下 <Enter> 键或 <Return> 键。

注册line事件:

  1. rl.on('line', (input) => {
  2. console.log(`接收到:${input}`);
  3. });

rl.question() 方法通过写入到 output 来展示 query,并等待用户提供到 input 的输入,然后调用 callback 函数并传入提供的输入作为第一个参数。

13 stream

Node.js 中有四种基本的流类型:

pipe:在可读流(readable stream)上调用 stream.pipe() 方法,并在目标流向 (destinations) 中添加当前可写流 ( writable ) 时,将会在可写流上触发 'pipe' 事件

readableSrc.pipe(writableDest)

可读流

  • data 事件,当流传递给消费者一个数据块的时候会触发。
  • end 事件,当在流中没有可以消费的数据的时候会触发。
  1. const fs = require('fs');
  2. const file = fs.createReadStream('./msg.txt', {
  3. flags: 'r', // 文件的操作方式,同readFile中的配置一样,这里默认是可读的是 r
  4. encoding: 'utf-8', // 编码格式
  5. autoClose: true, // 是否关闭读取文件操作系统内部使用的文件描述符
  6. start: 0, // 开始读取的位置
  7. end: 5, // 结束读取的位置
  8. highWaterMark: 1 // 每次读取的个数
  9. });
  10. file.on('open', () => {
  11. console.log('开始读取文件');
  12. });
  13. file.on('data', (data) => {
  14. console.log('读取到的数据:');
  15. console.log(data);
  16. });
  17. file.on('end', () => {
  18. console.log('文件全部读取完毕');
  19. });
  20. file.on('close', () => {
  21. console.log('文件被关闭');
  22. });
  23. file.on('error', (err) => {
  24. console.log('读取文件失败');
  25. });

暂停事件 file.pause();重新读取,需要使用 resume()方法

可写流

  • drain 事件,当可写流可以接受更多的数据时的一个标志。
  • finish 事件,当所有的数据都写入到底层系统中时会触发。
  1. const fs = require('fs')
  2. let rs = fs.createReadStream('./tools/赵雷 - 成都.mp3', { highWaterMark: 1024 })
  3. let ws = fs.createWriteStream('./chengdu.mp3', { highWaterMark: 1024 })
  4. function sleep ( n,rs ) {
  5. let start = new Date().getTime() ;
  6. while ( true ) {
  7. if ( new Date( ).getTime( ) - start > n ) {
  8. console.log('恢复');
  9. rs.read()
  10. rs.resume()
  11. break;
  12. }
  13. }
  14. }
  15. let i = 0
  16. console.log('初始',i)
  17. rs.on('data', function(chunk) {
  18. console.log('读取1024', i)
  19. i++
  20. console.log('当前长度', i)
  21. if (10 === i) {
  22. rs.pause()
  23. sleep(2000, rs)
  24. }
  25. console.log('读取进度', Math.trunc( (i * 1024)/13393628 * 100 ),'%')
  26. // 当ws.write() 返回false时,表示没有空间继续写入了,暂停读取
  27. if(ws.write(chunk) == false) {
  28. console.log('暂停rs的data事件');
  29. rs.pause() // 暂停rs的data事件
  30. }
  31. })
  32. ws.on('drain', function() {
  33. rs.resume() // 恢复rs的data事件 // 把当前读入的内容都写到文件中了,继续调用读写
  34. })
  35. // 当读取流触发end方法,表示读取完毕,这时关闭可写流的写入
  36. rs.on('end', function() {
  37. ws.end()
  38. })

管道流

  1. const fs = require('fs');
  2. // 读取msg.txt中的字符串 hello world
  3. const msg = fs.createReadStream('./msg.txt', {
  4. highWaterMark: 5
  5. });
  6. // 写入到1.txt中
  7. const f1 = fs.createWriteStream('./1.txt', {
  8. encoding: 'utf-8',
  9. highWaterMark: 1
  10. });
  11. const res = msg.pipe(f1);
  12. console.log(res);

14.定时器

setImmediate(callback[, ...args])

预定立即执行的 callback,它是在 I/O 事件的回调之后被触发

setInterval(callback, delay[, ...args])

预定每隔 delay 毫秒重复执行的 callback

setTimeout(callback, delay[, ...args])

预定在 delay 毫秒之后执行的单次 callback

16.URL

new URL(input[, base])

  1. const { URL } = require('url');
  2. const myURL = new URL('/foo', 'https://example.org/');
  3. // https://example.org/foo

17.Process 

process对象是Node的一个全局对象,提供当前Node进程的信息。它可以在脚本的任意位置使用,不必通过require命令加载。该对象部署了EventEmitter接口。

process.argv:返回当前进程的命令行参数数组。
process.env:返回一个对象,成员为当前Shell的环境变量,比如process.env.HOME。
process.installPrefix:node的安装路径的前缀,比如/usr/local,则node的执行文件目录为/usr/local/bin/node。
process.pid:当前进程的进程号。
process.platform:当前系统平台,比如win32。
process.title:默认值为“node”,可以自定义该值。
process.version:Node的版本,比如v16.17.1。

process.stdout: 标准输出,​​​​​​​它的write方法等同于console.log,可用在标准输出向用户显示内容

process.stdout.write('ssssss');//console.log('ssssss);

 输出文件

  1. fs.createReadStream('./files/input.txt')
  2. .pipe(process.stdout)

process.stdin: 标准输入

  1. process.stdin.setEncoding('utf8');
  2. let fs = require('fs');
  3. process.stdin.on('readable', function() {
  4. let chunk = process.stdin.read();
  5. if (chunk !== null) {
  6. process.stdout.write('data: ' + chunk);
  7. }
  8. });

将键盘输入的显示在控制台

process.stdin.pipe(fs.createWriteStream('./files/input3.txt'))

将键盘输入的显示在文件上

process.stderr: 指向标准错误

process.chdir():切换工作目录到指定目录。
process.cwd():返回运行当前脚本的工作目录的路径。
process.exit():退出当前进程。
process.getgid():返回当前进程的组ID(数值)不支持window系统
process.getuid():返回当前进程的用户ID(数值)。
process.nextTick():指定回调函数在当前执行栈的尾部、下一次Event Loop之前执行。
process.on():监听事件,并指定回调函数 比如uncaughtException。
process.setgid():指定当前进程的组,可以使用数字ID,也可以使用字符串ID。
process.setuid():指定当前进程的用户,可以使用数字ID,也可以使用字符串ID。


 process.exit() 来指定退出代码,直接退出,这会导致事件循环中的任务直接不被处理,以及可能导致数据的截断和丢失

正确安全的处理是,设置 process.exitCode,并允许进程自然退出

当前进程退出时,会触发exit事件,可以对该事件指定回调函数

  1. process.on('exit', function () {
  2. fs.writeFileSync('/tmp/myfile', '需要保存到硬盘的信息');
  3. });

注意,此时回调函数只能执行同步操作,不能包含异步操作,因为执行完回调函数,进程就会退出,无法监听到回调函数的操作结果​​​​​​​

当 Node.js 清空其事件循环并且没有其他工作要安排时,会触发 beforeExit 事件。例如在退出前需要一些异步操作,那么可以写在 beforeExit 事件中

  1. let hasSend = false;
  2. process.on("beforeExit", () => {
  3. if (hasSend) return; // 避免死循环
  4. setTimeout(() => {
  5. console.log("mock send data to serve");
  6. hasSend = true;
  7. }, 500);
  8. });
  9. console.log(".......");
  10. // 输出:
  11. // .......
  12. // mock send data to serve

 异常处理 try-catch 捕获异常,如果异常未捕获,可以通过监听 process 的 uncaughtException 事件,来处理未捕获的异常

  1. process.on("uncaughtException", (err, origin) => {
  2. console.log(err.message);
  3. });
  4. const a = 1 / b;
  5. console.log("abc"); // 不会执行

process.nextTick 把回调函数作为微任务,放入事件循环的任务队列中

结合使用:

  1. process.on('uncaughtException', (err, origin)=>{
  2. console.log(err.message);
  3. })
  4. process.nextTick(function () {
  5. console.log("next tick1");
  6. sess()
  7. console.log("next tick11"); //不会执行
  8. });
  9. process.nextTick(function () {
  10. console.log("next tick2");
  11. });
  12. console.log("immediate");

输出:

immediate
next tick1
sess is not defined
next tick2

18.Node.js 单线程异步非阻塞模式

同步阻塞方式:

比如,你打电话问老婆今晚吃什么,老婆在电话那边一直想啊想,你在电话这边不干别的,就一直等啊等,电话始终未挂,直到她说吃火锅,电话才挂掉。

同步非阻塞方式:

比如,你打电话问老婆今晚吃什么,老婆在电话那边一直想啊想,你在电话这边该干什么干什么,电话始终未挂,直到她说吃火锅,电话才挂掉。

异步阻塞方式:

比如,你打电话问老婆今晚吃什么,老婆说我想想,过一会跟你打话。你在电话这边什么也没干,就一直等着这个电话。

异步非阻塞方式:

比如,你打电话问老婆今晚吃什么,老婆说我想想,过一会跟你打话。你在电话这边想干什么干什么,如果有电话来了,再处理电话。

同步与异步是被调用方决定的,决定是马上给你答案,还是过会通知你,给你答案。

阻塞与非阻塞是调用方决定的,在等待结果的过程中, 是否还可以干其他事。

同步阻塞例子:

  1. console.log('开始读文件');
  2. let fileContext = fs.readFileSync('./files/input.txt')
  3. console.log('input.txt 文件内容',fileContext.toString());
  4. console.log('程序其他操作');
  5. let file2Context = fs.readFileSync('./files/output.txt')
  6. console.log('output.txt 文件内容',file2Context.toString());
  7. console.log('程序结束');

异步非阻塞例子:

  1. function ReadInput(){
  2. fs.readFile('./files/input.txt',(err,data)=>{
  3. console.log('input文件内容',data.toString());
  4. })
  5. }
  6. function ReadOutput(){
  7. return fs.readFile('./files/output.txt',(err,data)=>{
  8. console.log('output文件内容',data.toString());
  9. })
  10. }
  11. console.log('开始读input文件');
  12. ReadInput()
  13. console.log('开始读output文件');
  14. ReadOutput()
  15. console.log('程序结束');

19.HTTP / HTTPS / HTTP2

参考:https://www.jianshu.com/p/d9029f7227ea

https基于http的加密请求方式

http2是一个请求可以有多个响应

20.OS

序号方法 & 描述
1os.tmpdir()
返回操作系统的默认临时文件夹。
2os.endianness()
返回 CPU 的字节序,可能的是 "BE" 或 "LE"。
3os.hostname()
返回操作系统的主机名。
4os.type()
返回操作系统名
5os.platform()
返回编译时的操作系统名
6os.arch()
返回操作系统 CPU 架构,可能的值有 "x64"、"arm" 和 "ia32"。
7os.release()
返回操作系统的发行版本。
8os.uptime()
返回操作系统运行的时间,以秒为单位。
9os.loadavg()
返回一个包含 1、5、15 分钟平均负载的数组。
10os.totalmem()
返回系统内存总量,单位为字节。
11os.freemem()
返回操作系统空闲内存量,单位是字节。
12os.cpus()
返回一个对象数组,包含所安装的每个 CPU/内核的信息:型号、速度(单位 MHz)、时间(一个包含 user、nice、sys、idle 和 irq 所使用 CPU/内核毫秒数的对象)。
13os.networkInterfaces()
获得网络接口列表。
  1. var os = require("os");
  2. // CPU 的字节序
  3. console.log('endianness : ' + os.endianness());
  4. // 操作系统名
  5. console.log('type : ' + os.type());
  6. // 操作系统名
  7. console.log('platform : ' + os.platform());
  8. // 系统内存总量
  9. console.log('total memory : ' + os.totalmem() + " bytes.");
  10. // 操作系统空闲内存量
  11. console.log('free memory : ' + os.freemem() + " bytes.");

21. 事件循环

js作为浏览器脚本,决定了它只能是单线程的,一些耗时任务会导致浏览器卡顿.因此js将任务分成了同步任务和异步任务.

同步和异步任务分别进入不同的执行”场所”,同步的进入线程,异步的进入任务列表,当线程里面的任务执行完成,从异步任务列表拿出任务在线程里面执行,当前的任务执行完成在从任务列表拿出来在线程里面执行,这个过程就是事件循环

异步任务又分为宏任务和微任务,不同的任务进入不同的任务栈.先执行所有的微任务,在进入宏任务执行微任务...

  • macro-task(宏任务):包括整体代码script,setTimeout,setInterval
  • micro-task(微任务):Promise,process.nextTick

Promise 新建一个实例时,会立即执行

  1. setTimeout(function() {
  2. console.log('setTimeout');
  3. })
  4. new Promise(function(resolve) {
  5. console.log('promise');
  6. resolve()
  7. }).then(function() {
  8. console.log('then');
  9. })
  10. console.log('console');
  11. //结果
  12. promise
  13. console
  14. then
  15. setTimeout

1.这段代码作为宏任务,进入主线程
2.先遇到setTimeout,加入宏任务队列
3.接下来遇到了Promise,new Promise立即执行,then函数加入到微任务队列
4.遇到console.log()同步任务,立即执行
5.好啦,整体代码script作为第一个宏任务执行结束,看看有哪些微任务?我们发现了then在微任务Event Queue里面,执行
5.ok,第一轮事件循环结束了,我们开始第二轮循环,当然要从宏任务Event Queue开始。我们发现了宏任务Event Queue中setTimeout对应的回调函数,立即执行
结束
 

  1. console.log('1');
  2. setTimeout(function() {
  3. console.log('2');
  4. process.nextTick(function() {
  5. console.log('3');
  6. })
  7. new Promise(function(resolve) {
  8. console.log('4');
  9. resolve();
  10. }).then(function() {
  11. console.log('5')
  12. })
  13. })
  14. process.nextTick(function() {
  15. console.log('6');
  16. })
  17. new Promise(function(resolve) {
  18. console.log('7');
  19. resolve();
  20. }).then(function() {
  21. console.log('8')
  22. })
  23. setTimeout(function() {
  24. console.log('9');
  25. process.nextTick(function() {
  26. console.log('10');
  27. })
  28. new Promise(function(resolve) {
  29. console.log('11');
  30. resolve();
  31. }).then(function() {
  32. console.log('12')
  33. })
  34. })

// 1  7  6  8 2 4 3 5 9 11 10 12

1.这段代码作为宏任务,进入主线程

2.遇到console.log()同步任务,立即执行 输出1

3.遇到setTimeout,添加到到宏任务Event Queue

4.遇到process.nextTick,添加到到微任务Event Queue

5.遇到new Promise,立即执行,输出7

6.then函数加入到微任务队列

7.遇到setTimeout,添加到到宏任务Event Queue

8.好啦,整体代码script作为第一个宏任务执行结束,看看有哪些微任务?上面的4和6是微任务,

按先后顺序输出6,8

9.第一轮事件循环结束,开始第二轮,查找序号3宏任务执行,遇到console.log()同步任务,输出2

10.遇到process.nextTick,加入到微任务队列

11.遇到new Promise,立即执行,输出4

12.then函数加入到微任务队列

13.ok,当前的宏任务结束,查看微任务,查看微任务序号10,11,按顺序输出3,5

14.微任务执行完成,开始下一个宏任务setTimeout,序号7,,遇到console.log()同步任务,输出9

15.后面的与第一个setTimeout一样,输出11,10,12

微任务队列中,process.nextTick执行优先级高于其他微任务

宏任务根据类型不同分为以下几种:

Timers 类型的宏任务队列

  • setTimeout()

  • setInterval

Check 类型的宏任务队列

  • setImmediate()

Poll 类型的宏任务队列

  • 除了上面几种的其他所有回调

宏任务里面执行顺序:Timers --> Poll -->Check---

Timers 阶段执行将到期任务从任务栈取出执行

poll 阶段执行到期回调

  1. const fs=require('fs')
  2. fs.readFile('test.txt',()=>{
  3. console.log(' 0')
  4. setTimeout(()=>{
  5. console.log(' 1');
  6. })
  7. setImmediate(()=>{
  8. console.log(' 2')
  9. })
  10. setTimeout(()=>{
  11. console.log(' 3');
  12. })
  13. })
  14. setTimeout(()=>{
  15. console.log(' 4');
  16. })
  17. setTimeout(()=>{
  18. console.log(' 5');
  19. },100)
  20. setImmediate(()=>{
  21. console.log(' 6')
  22. })
  23. console.log(' 7');

1.进入主线程,readFile加入宏任务

2.setTimeout加入异步宏任务

3.setTimeout加入异步宏任务

4.setImmediate加入异步宏任务

5.同步任务,直接输出7

6.time阶段检测到到期的任务,输出4

7.poll阶段 读取文件还没有完成

8.check阶段 setImmediate输出6

9.进入下轮循环,setTimeout还没有到期

10.进入poll阶段,读取文件完成,输出0

11.check阶段 setImmediate输出2

12.将读文件回调里面的setTimeout加入宏任务队列

13.进入下轮循环,执行到期的setTimeout,输出1,3

14..进入poll阶段,没有任务,check阶段没有任务,下轮循环

15..time阶段检测到到期的任务,输出5

结果: 7 4 6 0 2 1 3 5

如果将打印1的事件间隔100执行,即

  1. const fs=require('fs')
  2. fs.readFile('test.txt',()=>{
  3. console.log(' 0')
  4. setTimeout(()=>{
  5. console.log(' 1');
  6. },100)
  7. setImmediate(()=>{
  8. console.log(' 2')
  9. })
  10. setTimeout(()=>{
  11. console.log(' 3');
  12. })
  13. })
  14. setTimeout(()=>{
  15. console.log(' 4');
  16. })
  17. setTimeout(()=>{
  18. console.log(' 5');
  19. },100)
  20. setImmediate(()=>{
  21. console.log(' 6')
  22. })
  23. console.log(' 7');

输出结果: 7 4 6 0 2 3 5 1

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/69043
推荐阅读
相关标签
  

闽ICP备14008679号