我是靠谱客的博主 闪闪大船,这篇文章主要介绍Node.Js基础知识,现在分享给大家,希望可以做个参考。

Node.Js架构Node.Js架构

Natives modules

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

Builtin modules 胶水层

  • 在V8引擎下,主要是帮助我们调用一些c/c++的功能,比如:sockethttp 等

具体功能模块

V8

  • 提供初始化工作,创建执行上下文环境和作用域
  • 执行JS代码(自己的代码、内置代码、第三方代码),提供桥梁接口(我们调用的函数可能是c/c++实现,主要js与c/c++的转换功能)

libuv

  • 事件循环、事件队列、异步IO

第三方模块:c-ares(DNS)、http(parse)、zlib

数据流程

数据流程
主流后端语言处理多任务的时候,通常是开多线程。但是当任务量比较少时,线程就会浪费(服务员例子)。因此出现了 Reactor模式(应答者模式),单线程完成多线程工作。可以避免多个线程在上下文切换过程中考虑的状态保存、时间消耗、状态锁。
请添加图片描述
因此:NodeJS 更适合用于IO密集型高并发请求

NodeJS异步IO

同步时间:= 任务一 + 任务二
异步时间:< 任务一 + 任务二
请添加图片描述
异步IO内部会 轮询 IO 状态,重复调用IO操作,判断IO是否结束。
常见轮询技术:read、select、poll、kqueue、event ports

期望无需主动判断的被阻塞IO ->libuv
请添加图片描述
NodeJS异步操作过程
请添加图片描述
异步IO总结

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

事件驱动架构

事件驱动架构是软件开发中的通用架构
主体发布消息,原来注册事件的其他实体接收到消息后就会处理响应事件

复制代码
1
2
3
4
5
6
7
8
9
10
let eventEmitter = require("events"); const myEvent = new eventEmitter(); myEvent.on("事件1", function(){ console.log("事件1被触发了"); }) myEvent.emit("事件1");

NodeJs单线程

单线程如何实现高并发?
异步IO、事件循环加上事件驱动的架构配合事件回调通知

NodeJs主线程是单线程,但是在libuv 库中存在线程池

但是如果处理cpu密集型就不太行了:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const http = require("http"); function sleep(time) { const end = Date.now() + time * 1000; while(Date.now() < end) {} return; } // 睡4秒 sleep(4); const server = http.createServer((req, res) => { res.end("createServer start..."); }) server.listen(8080, () => { console.log("服务器启动了"); })

NodeJs 应用场景

  • NodeJs作为中间层
    请添加图片描述
  • 操作数据库提供服务
  • 实时聊天业务程序
  • 前端工程化

NodeJs 适合IO密集型任务,不适合大量的业务逻辑

node api 牛刀小试

  1. 安装全局TS,ts-node
  2. 书写主逻辑
    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import express from "express"; import { DataStore } from './data'; const app = express(); app.get("/", (req, res) => { res.json(DataStore.list); }); app.listen(8080, ()=>{ console.log("服务开启"); })
  3. 创建json 文件,并创建处理文件data.ts。在ts 导入json 文件时,会提示报错,我们要设置tsconfig.json 文件中的"resolveJsonModule": true
    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // json 文件 [ { "name": "hyb", "age": 18 }, { "name": "hsf", "age": 19 } ] // data.ts import list from "./list.json"; export class DataStore { static list = list }

NodeJS全局对象

  • 与浏览器平台的window不完全相同
  • NodeJs全局对象上挂载许多属性
  • NodeJs全局对象是global,根本作用是全局变量的宿主

全局变量

  • __filename:返回正在执行脚本文件的绝对路径
  • __dirname:返回正在执行脚本所在目录
  • timer类函数:执行顺序与时间循环间的关系
  • process:提供与当前进程互动的接口
  • require:实现模块的加载
  • module、exports:处理模块的导出
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 全局对象 // console.log(global); // 文件和 文件夹路径 // console.log(__filename); // console.log(__dirname); // 默认情况下 this 是空对象,和 global 是不一样的 console.log(this); console.log(this == global); // 我们可以理解为,在我们执行js 文件时,内部会帮 // 我们封装成下面立即调用的情况,会将全局对象,全局变量作为 // 参数传进来,所以我们无需引用直接调用 (function(){ console.log(this == global); })()

全局变量process

  • 获取进程信息
  • 执行线程操作
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 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.HOME); // USERPROFILE // console.log(process.platform); // 3. 运行状态:启动参数、PID、运行时间 // console.log(process.argv); // console.log(process.argv0); // console.log(process.pid); // console.log(process.uptime()); // 4. 事件 // process.on("beforeExit", (code) => { // console.log("before exit " + code); // }) // process.on("exit", (code) => { // console.log("exit" + code); // }) // console.log("代码执行完毕"); // 5. 标准输出 输入 错误 // console.log = function (data) { // process.stdout.write("---" + data + "n"); // } // console.log(11); // console.log(22); // 读取文件 // const fs = require('fs'); // fs.createReadStream('test.txt').pipe(process.stdout); // 读取 和写东西 // process.stdin.pipe(process.stdout);

path

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
const path = require("path"); /** * 返回路径的最后一部分,通常用于从路径中提取文件名 * 传入后缀字符串参数时,若结果包含后缀字符串,则返回从结果中删除扩展后的字符串 * 若最后结尾是路径分割符,则忽略 */ console.log(__filename); console.log(path.basename(__filename)); console.log(path.basename(__filename, 'h.js')); console.log(path.basename(__filename, '.css')); console.log(path.basename("a/b/c")); console.log(path.basename("a/b/c/", "c")); console.log("华丽分割线-------------------") // 返回文件路径名 console.log(path.dirname(__filename)); console.log("华丽的分割线----------------------") /** * 返回文件的扩展名 * path 路径中存在多个点,匹配最后一个点到结尾 */ console.log(path.extname(__filename)); console.log("华丽的分割线----------------------") // 解构路径 console.log(path.parse(__filename)); console.log("华丽的分割线----------------------") // 序列化路径 console.log(path.format(path.parse(__filename))); console.log("华丽分割线------------------------") // 是否为绝对路径 console.log(path.isAbsolute('./foo')); console.log(path.isAbsolute('/foo')); console.log("华丽分割线---------------------") // 拼接路径 console.log(path.join("a/b", 'c', 'a.html')); console.log(path.join("a/b", 'c', "../",'a.html')); console.log("华丽分割线---------------------") // 规范化路径 console.log(path.normalize("a//b/c")) console.log("华丽分割线---------------------") // 绝对路径 console.log(path.resolve("a.html")); console.log(path.resolve("/a.html"));

Buffer

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。
但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。
Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。

最后

以上就是闪闪大船最近收集整理的关于Node.Js基础知识的全部内容,更多相关Node内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(78)

评论列表共有 0 条评论

立即
投稿
返回
顶部