Node.js

113 阅读4分钟

含意

node.js是开源的跨平台的JavaScript运行环境# 含意

node.js是开源的跨平台的JavaScript运行环境

JS的运行环境

浏览器运行环境

image.png

Node运行环境

image.png

浏览器可以使用DOM,node不行

进程与线程

软件被保存在硬盘中,运行在内存中。软件的运行实例叫做进程。一个进程包括多个线程

模块

模块基础

CommonJS

导入

const fs = require('fs')

导出

  •   module.exports = value
    
  •   exports.name = value
    

module.exports可以暴露任意数据,require本质是引入module.exports

不可以使用exports=xxx暴露数据,只能exports.xxx为暴露的对象添加属性

ES6

导入

import

导出

export

差别

  1. 动态与静态
    1. CommonJS模块是动态加载的,即在运行时根据需要加载模块。
    2. ES6模块是静态加载的,即在编译时就确定了模块的依赖关系。
  2. 异步加载
    1. CommonJS模块加载是同步的,即在导入模块时会阻塞后续代码的执行,直到模块加载完成。
    2. ES6模块加载是异步的,即在导入模块时不会阻塞后续代码的执行,模块会在需要时动态加载。

fs模块

I/O操作一般都是异步操作,当执行完毕后会将回调加入任务队列

模块的导入

const fs = require('fs')

路径模块

模块导入

const path = require('path')

常用方法:

  • path.resolve:拼接规范的绝对路径

路径

  • 相对路径
./index.html
  • 绝对路径
D:./index.html

问题

工作区不固定,然而相对路径是根据工作区。为了解决相对路径错位引入__dirname。使用path.resolve(__dirname+相对路径)来定位文件。

__dirname:所在文件所在目录的绝对路径

http模块

导入模块

const http = require('http')

创建服务对象

cosnt sever = http.createServer((req,res) => { //请求体,响应体
  res.end('')//响应体
})

监听端口、启动服务

sercer.lsiten(端口号,() => {}) //端口号,启动回调

Express框架

是一个灵活的WEB应用开发框架

基本流程

  1. 导入express
  2. 创建应用对象
  3. 创建路由
  4. 监听端口、启动服务
const express = require('express');
const app = express();

// 定义路由
app.get('/', (req, res) => {
  // 渲染模板并传递数据
  res.render('index', { title: 'Express Server Template' });
});

// 启动服务器
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

中间件

本质是一个回调函数,可以向路由回调一样访问请求对象,响应对象(req、res)

  • 全局中间件:所有请求都会被调用
  • 路由中间件:只有匹配路由的请求才会被调用
const express = require('express');
const app = express();

function fun((req, res, next) => {
  console.log('This is a router middleware');
  next();
})

// 全局中间件
app.use(fun);

// 路由中间件
app.get('/',fun,(req, res) => {
  res.send('Hello, World!');
});


// 启动服务器
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

NodeJS原理

NodeJS单线程架构模型

nodejs并不是真正的单线程架构,其中还有I/O线程(网络I/O、磁盘I/O)等,这些线程是由更底层的libuv通过事件循环处理,js运行在v8上是单线程的。

image.png

NodeJS的事件循环机制

事件循环允许Node.js执行非阻塞I/O操作。尽管JavaScript是单线程的,通过尽可能将操作卸载到系统内核。由于大多数现代内核都是多线程的,因此它们可以处理在后台执行的多个操作。当其中一个操作完成时,内核会告诉Node.js,以便可以将相应的回调添加到轮询队列中以最终执行。

image.png  EventLoop 中的 6个步骤都是相对于宏任务。NodeJs执行完成一个宏任务后会立即清空当前队列中产生的所有微任务。

  • timers:执行setTimeout(),setInterval()回调函数

  • pending callbacks:执行I/O回调

  • idle,prepare:在NodeJs内部调用,无法操作

  • poll:获取新的I/O事件

image.png 如果轮询队列不是空的,事件循环将循环访问回调队列并同步执行它们,直到队列已用尽,或者达到了与系统相关的硬性限制。

如果轮询队列是空的,还有两件事发生:

    - 如果脚本被 setImmediate() 调度,则事件循环将结束 poll(轮询) 阶段,并继续 check(检查) 阶段以执行那些被调度的脚本。
    - 如果脚本 未被 setImmediate()调度,则事件循环将等待回调被添加到队列中,然后立即执行。
  • check:执行setImmediate回调

  • close callbacks:setImmediate

nodejs特点

  1. 事件驱动 主线程通过event loop事件循环触发的方式来运行程序

  2. 非阻塞异步I/O模型

    node 具有异步 I/O 特性,每当有 I/O 请求发生时,node 会提供给该请求一个 I/O 线程。然后 node 就不管这个 I/O 的操作过程了,而是继续执行主线程上的事件,只需要在该请求返回回调时再处理即可。也就是 node 省去了许多等待请求的时间。

  3. 轻量高效

  • 阻塞和非阻塞主要描述的是程序或线程在等待系统调用结果时的状态
  • 同步和异步主要描述的是**程序或线程之间的交互模式