一、概述

NodeJs可以做什么?

  • 轻量级、高性能的web服务器
  • 前后端javsscript同构开发
  • 便捷高效的前端工程化

二、nodejs架构

在这里插入图片描述

  • 当前层内容由js实现
  • 提供应用程序可直接调用库,例如fs、path、http等
  • JS语言无法直接操作底层硬件设置

在这里插入图片描述
底层

  • V8:执行 JS 代码,提供桥梁接口
  • Libuv:事件循环、事件队列、异步IO
  • 第三方模块:zlib、http、c-area等

在这里插入图片描述

三、为什么是nodejs

Nodejs 慢慢演化为了一门服务端“语言”

在这里插入图片描述
IO是计算机操作过程中最缓慢的环节

在这里插入图片描述
Reactor模式,单线程完成多线程工作
Reactor模式下实现异步IO、事件驱动
Nodejs更适用于IO密集型高并发请求

四、Nodejs 异步IO(node事件循环)

首先,node.js的事件循环与JavaScript的略有不同。node中事件循环使node.js可以通过将操作转移到系统内核中来执行非阻塞 I/O操作。由于大多数现代内核都是多线程的,因此它们可以处理在后台执行的多个操作。当这些操作之一完成时,内核会告诉node.js,以便可以适当的回调添加到轮询队列中以最终执行。

在 Node.js 中,事件循环是由 libuv 库实现的,它是一个跨平台的高性能异步 I/O 库。事件循环机制允许 Node.js 在运行过程中不断处理事件并执行回调函数,以实现非阻塞的异步操作。

在这里插入图片描述
在这里插入图片描述

  • timers队列:存放计时器的回调函数
  • poll轮询队列:除了times、checks,绝大部分回调都会被放入该队列,比如:文件的读取、监听用户请求等;如果poll中有回调,依次执行回调,直到清空队列。如果poll中没有回调,等待其他队列中出现回调,结束该阶段,进入下一阶段,如果其他队列也没有回调,持续等待,直到出现回调为止。
  • check检查队列:使用setImmediate的回调会直接进入这个队列
  • nextTick和Promise:事件循环中,每次打算执行一个回调之前,必须清空nexrTick和promise队列

在这里插入图片描述

在这里插入图片描述

异步 IO 总结

  • IO 是应用程序的瓶颈所在
  • 异步 IO 提高性能无采原地等待结果返回
  • IO 操作属于操作系统级别,平台都有对应实现
  • Nodeis 单线程配合事件驱动架构及libuv实现了异步IO

大厂面试题


async function async1(){
  console.log("1");
  await async2();
  console.log("2");
}
async function async2(){
  console.log("3");
}
console.log("4");
setTimeout(()=>{
  console.log(5);
},0);
setTimeout(()=>{
  console.log("6");
},3);
setImmediate(()=> console.log("7"));
process.nextTick(()=> console.log("8"));
async1();
new Promise(function(resolve){
  console.log("9");
  resolve();
  console.log("10");
}).then(function(){
  console.log("11");
});
console.log("12");

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

五、事件驱动

事件驱动、发布订阅、观察者

发布订阅

const EventEmitter = require('events')

const myEvent = new EventEmitter()

myEvent.on('事件1', () => {
  console.log('事件1执行了')
})

myEvent.on('事件1', () => {
  console.log('事件1-2执行了')
})

myEvent.emit('事件1')

在这里插入图片描述

六、nodejs实现api服务

ts-node是直接运行ts的第三方包

server.ts

// 需求:希望有一个服务,可以依据请求的接口内容返回相应的数据
import express from 'express'
import { DataStore } from './data'

// console.log(DataStore.list)

const app = express()

app.get('/', (req, res) => {
  // res.end('1122')
  res.json(DataStore.list)
})

app.listen(8080, () => {
  console.log('服务已经开启了')
})

ts-node .\server.ts

七、nodejs全局对象

  • __filename:返回正在执行脚本文件的绝对路径
  • __dirname:返回正在执行脚本所在目录
  • timer类函数:执行顺序与事件循环间的关系
  • process:提供与当前进程互动的接口
  • require:实现模块的加载
  • module、exports:处理模块的导出

八、全局对象process - 1

// 1 资源: cpu 内存
// console.log(process.memoryUsage())
// console.log(process.cpuUsage())

// 2 运行环境:运行目录、node环境、cpu架构、用户环境、系统平台
/* console.log(process.cwd())
console.log(process.version)
// console.log(process.versions)
console.log(process.arch)
console.log(process.env.NODE_ENV)
// console.log(process.env.PATH)
console.log(process.env.USERPROFILE)  // HOME
console.log(process.platform) */

// 3 运行状态: 启动参数、PID、运行时间
console.log(process.argv) // 可以获取执行脚本命令传入的参数
console.log(process.argv0)  // execArgv
console.log(process.pid)   // ppid 


console.log(process.uptime()) //  脚本运行时间

案例 对一个文件进行md5加密

md5.js

const crypto = require('crypto');
const fs = require('fs');

function md51(path) {
	let buffer = fs.readFileSync(path);
	let fsHash = crypto.createHash('sha1');

	fsHash.update(buffer);
	return fsHash.digest('hex');
}

function md52(path) {
	let buffer = fs.readFileSync(path);
	let fsHash = crypto.createHash('sha256');

	fsHash.update(buffer);
	return fsHash.digest('hex');
}
console.log(md51(process.argv[2]));
console.log(md52(process.argv[2]));

执行 node md5.js 律动v0_4_3_20220808_mac_M1.zip

九、全局对象process - 2

脚本执行事件

process.on('exit', (code) => {
  console.log('exit' + code)
})

process.on('beforeExit', (code) => {
  console.log('exit' + code)
})

console.log('代码执行完了')

在这里插入图片描述

process.exit() //主动退出
console.log(1111) //不会执行
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐