Bootstrap

【node.js】 node学习笔记

目录

一.node的特点 

二.node在实际项目中的应用

三.node的架构

node中如何实现异步IO?

node事件驱动架构?

四.node全局对象及全局变量

1.全局变量process

2.setImmediate

3.process.nextTick

四.模块管理机制

3.1 模块化原理解析

3.2 require方法加载规则

四.fs内置模块

五.path内置模块

六.url内置模块

七.http内置模块

八.node事件循环

node中的宏任务和微任务

node事件循环完整过程

不同node版本宏任务和微任务的执行差异

setTimeout和setImmediate的执行顺序

九.Express基本使用

1.基本服务器搭建

2.中间件的使用

3.路由


 

一.node的特点 

1.基于V8引擎(webkit内核)渲染和解析JS(类似的还有webview和谷歌浏览器等),它不是后台语言,它是一个工具或环境,用来解析js的工具或者环境。我们一般会把node安装在服务器上,在服务器上写一些js代码,实现服务端的一些功能。基于命令node xxx.js把js代码运行在node环境下

2. 单线程异步非阻塞的I/O操作

JS在客户端浏览器中运行,是否可以对客户端本地的文件进行读写操作?

不能,要保证客户端的信息安全。input:type="file" 文件上传表单除外,但这种也需要用户手动进行选择才可以。

JS在服务器运行能否对服务端的文件进行操作?

可以,node赋予js进行I/O读写的能力(内置模块FS)

3.window 和 global

1)在客户端浏览器中运行的js,js的全局对象是window,它提供了很多内置的属性和方法          

2)在node中运行js,js全局对象是global, 也包括许多内置的属性

1.proceess:node中做进程管理的属性,常用有

        - process.nextTick()

        - process.env

2.Buffer:数据格式管理的;

3.setImmediate 立刻执行(类似于setTimeout(fun,0))

注意:在REPL命令中输出this是global,但在xxx.js中输出的this是当前模块本身。

4.不适合处理CPU密集型的任务

nodejs是单线程的,如果遇到涉及到较大计算量的cpu密集型的任务,其后面的代码是不会执行的。但配合异步IO和事件循环是可以处理一些高并发的请求的。

let http = require('http');

function sleepTime (time) {
    const sleep = Date.now() + time * 1000;
    while(Date.now() < sleep) {}
    return;
}

sleepTime(4);  // 这就是一个cpu密集型的任务,占用主线程

const server = http.createServer((req,res) => {
    res.end('server starting');
});

server.listen(8080,() => {
    console.log('start on 8080......');
})

二.node在实际项目中的应用

1)webpack是基于node环境运行的

2)npm是安装了node后自带的模块管理工具,基于它可以安装和卸载对应的模块

3)基于node.js实现服务器的功能操作

项目架构1基于node.js架构全栈项目(一般用于中小型项目)

abee33d623894eb09730abb97d8d2cc6.png

项目架构2基于node.js构建中间层

特点:单线程异步,无阻塞I/O,事件驱动。node.js作为服务层,抗压和抗并发的能力不错

e2e3f8421e984e9f84e132fb0c64e264.png

这种方式,可以基于node.js实现跨域访问,客户端和中间层在一个域下(同源),基于中间层从第三方服务器上获取数据(node.js可以跨域获取数据)

另外,当客户端和服务器同时进行开发的时候,需要两端协商接口规范(API文档),然后由服务端先开发出一个伪接口,有时这个伪接口就是基于node.js开发的一套数据mock的后台,在项目联调的时候,再把接口切换到真实的后台上。

项目架构3:基于node.js实现服务器渲染

客户端数据绑定后在源代码中看不到绑定的内容,不利于SEO优化。所以有些产品需要放弃客户端渲染,改为服务器渲染,这个渲染操作就由node处理。

5a4e27ca5ae84381afbfe843d27f8248.png

三.node的架构

nodejs的核心是由三层组成。最上层Native modules是内置核心模块,里面暴露了js的内置功能模块接口;中间层Bindings是在使用对应模块时调用对应模块的c++函数的,且需要V8引擎配合完成;最下层包括许多模块,其中V8引擎用于构建js代码的运行环境,负责js代码的执行,js和底层c++代码的转换;libuv库用于处理node的事件循环,事件队列,异步IO;除此之外还有其他若干模块对应不同的功能。

7a309d20f55040dd97d0bd3a7c280287.png

node中如何实现异步IO?

对于IO分为阻塞和非阻塞两种类型,对于非阻塞的IO,CPU的时间片可以处理其他的事务,从而提升性能,但立即返回的不是最终需要的数据,而是调用的状态,操作系统为了得到最终的数据,会使用轮询让应用程序重复调用IO操作,从而确认IO操作是否已经完成,一旦完成就将最终的数据返回,但此时程序依旧等待IO的结果,依旧是阻塞的。在node中使用libuv库,在IO操作调用发起后直接进行下一个操作的处理,等待IO的结果处理完后,通知js主线程通过回调的方式将结果传递给当前代码。 nodejs单线程配合事件驱动架构及libuv实现异步IO。

node事件驱动架构?

类似消息订阅发布模式,发布者广播消息,订阅者接受消息。

2fe6ea5a52244ce4887050bf0018b09c.png

当libuv库接收到了异步IO操作时,事件多路分解器找到当前平台环境下可用的IO处理接口,等待IO操作结束后通过对应的事件添加到事件队列中,随后按照顺序从事件队列中取出事件交给主线程执行。在接收到IO操作时,会发布某个事件,事件的订阅者在IO操作结果返回后执行在订阅时的处理程序,获取结果。

node事件驱动简单代码实现:

let eventEmitter = require('events');
const myEvent = new eventEmitter();

// 绑定事件event1,订阅者
myEvent.on('event1',() => {
    console.log('event1执行了');
});

// 触发事件event1,发布者
myEvent.emit('event');

四.node全局对象及全局变量

node中提供关键字global表示全局对象,其上挂载了许多属性和方法。

node中this和global的关系

在node中默认this是空对象,直接判断this和global的关系两者不相等,但在自调用函数中判断两者是相等的。因为在node中每一个文件都是一个独立的模块,每一个模块在执行的时候最外层都被包裹了一个自调用的函数,node会为该函数传递一些固定的参数,例如:__filename,require,__dirname,exports等,包括this;

console.log(this); // {}
console.log(this === global);  // false

(function () {
    console.log(this === global);  // true
})()

1.全局变量process

作用:获取当前正在执行脚本的信息,对当前进程进行一些操作等

1)process.memoryUsage():查看当前脚本内存使用信息

console.log(process.memoryUsage());

输出对象如下: 

30226916d1404d6c937405d7aa0a2be3.png

2)process.cpuUsage():获取当前cpu的信息

console.log(process.cpuUsage());

获取的是用户和操作系统占用的当前CPU的时间片段 

;