Node.js是什么?
Node. js是一个基于 Chrome v8引擎的服务器端 JavaScript运行环境;Node. js是一个事件驱动、非阻塞式I/O的模型,轻量而又高效;Node. js的包管理器npm是全球最大的开源库生态系统。
Node. js的使用场景是什么?
高并发、实时聊天、实时消息推送、客户端逻辑强大的SPA(单页面应用程序)。
为什么要用 Node. js?
(1)简单, Node. js用 JavaScript、JSON进行编码,简单好学。
(2)功能强大,非阻塞式I/O,在较慢的网络环境中,可以分块传输数据,事件驱动,擅长高并发访问。
(3)轻量级, Node. js本身既是代码又是服务器,前后端使用同一语言。
(4)可扩展,可以轻松应对多实例、多服务器架构,同时有海量的第三方应用组件。
Node的基本用法
方法一:在终端输入 node “js文件所在路径地址”,点击Enter运行

例如要运行的service.js文件,就输入:node ./service.js 点击运行即可在终端运行node文件并输出文件内容
方法二:直接在终端输入 node,进入node环境,然后输入node指令即可

如果要退出node环境,按Ctrl + C即可退出
相关拓展
单线程和同步异步
JS语言的一大特色就是单线程,所谓单线程就是,同一时间只能做一件事。为什么JS不能有多个线程呢?因为JS主要用途是与用户进行交互以及操作DOM。这就决定了它只能是单线程,否则假设有多个线程,一个线程在某个DOM节点上添加内容,同时另一个线程又要删除这个节点,这时浏览器该以谁为准?
JS是一门单线程语言,它有一个主线程(main thread)和调用栈(也叫执行栈call-stack),所有的任务都会被放到调用栈等待主线程执行。单线程就意味着所有任务需要排队,前一个任务结束,才执行下一个任务。但是如果前一个任务耗时很长,后一个任务就需要一直等着了。如果其中一个任务很慢,占用很多时间,此时网页就会卡住。而有些I/O(输入输出)操作是很慢的,比如AJAX操作。
所以JS语言的设计者意识到,主线程可以先不管这些I/O操作,把等待中的任务先挂起,先运行排在后面的任务。等到I/O操作返回结果后,再去执行挂起的任务。
因此任务可以分为两种,一种是同步任务,一种是异步任务。
同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才执行下一个任务。
异步任务指的是,不进入主线程,而是进入任务队列,通过Event Loop机制等待合适的时间调用。
有了Event Loop的加持,JS才能非阻塞地运行。
同步任务与异步任务的流程图:

宏任务和微任务
宏任务:
宏任务Macro task,也叫tasks。一些异步任务的回调会依次进入Marco task queue,等待后续被调用。
宏任务包括:整体代码script,ajax网络请求,setTimeout,setInterval,node中的setImmediate、node的I/O操作,requestAnimationFrame(浏览器独有)、UI rendering(浏览器独有)等。
微任务:
微任务Micro task,也叫jobs。另一些异步任务的回调会依次进入Micro task queue,等待被调用。
微任务包括:Promise.then(),async,await,node中的process.nextTick()等。
事件循环,宏任务,微任务的关系如图所示:

事件循环Event Loop步骤流程
1.一开始执行全局的Script代码,这些代码中有同步语句或者异步语句,遇到同步语句直接执行,异步语句放入事件队列中。异步语句中不同类型的任务会进入对应的Event Queue,宏任务中的事件放在callback queue中,由事件触发主线程维护;微任务的事件放在微任务队列中,由js引擎线程维护。
2.全局的Script代码执行完毕之后,调用栈Stack会清空,然后先检查事件队列中的微任务队列中是否有任务。
3.如果有就从微任务队列中取出位于队首的回调,放入调用栈Stack中执行,执行完成之后,微任务队列长度相应减一。
4.如果微任务队列中还有任务,继续取出位于队首的任务,放入调用栈Stack中执行,以此类推,直到把微任务队列中所有的任务都执行完毕。注意,如果在执行微任务过程中又产生了新的微任务,那么会加入到微任务队列的队尾,也会在这个周期内被执行。
5.当微任务队列中所有任务都执行完毕之后,此时微任务队列为空,调用栈Stack清空,检查事件队列中的宏任务队列中是否有任务。
6.如果有,依次取出宏任务队列中位于队首的任务放入调用栈Stack中执行。
7.主线程每次将执行栈清空后,就去事件队列中检查是否有任务,如果有,就每次取出一个推到执行栈中执行,这个循环往复的过程就被称为“Event Loop事件循环”。
小测试:
console.log(1)
setTimeout(()=>{
console.log(2)
}, 0)
new Promise((resolve, reject)=>{
console.log('new Promise')
resolve()
}).then(()=>{
console.log('then')
})
console.log(3)
复制代码
结果是:1 => 'new Promise' => 3 => 'then' => 2
流程如下
// 遇到 console.log(1) ,直接打印 1
// 遇到定时器,属于新的宏任务,留着后面执行
// 遇到 new Promise,new Promise是在解析生成promise对象,里面的操作是同步的,直接执行,打印 'new Promise'
// .then 属于微任务,放入微任务队列,后面再执行
// 遇到 console.log(3) 直接打印 3
// 好了本轮宏任务执行完毕,现在去微任务列表查看是否有微任务,发现 .then 的回调,执行它,打印 'then'
// 当一次宏任务执行完,再去执行新的宏任务,这里就剩一个定时器的宏任务了,执行它,打印 2
复制代码
promise
Promise是一个对象,代表一个异步操作的最终完成或者失败。由于它的then、catch、finally方法会返回一个新的promise对象,所以可以允许我们链式调用,解决了由于传统的函数嵌套函数所导致的回调地狱问题。
promise的三种状态:
pending、resolved、rejected
Promise的状态一经改变就不能再改变
1.pending状态,不会触发then和catch
2.resolved状态,会触发后续的then回调函数
3.rejected状态,会触发后续的catch回调函数
4.then正常返回的状态是resolved,里面有报错则返回rejected
5.catch正常返回的状态是resolved,里面有报错则返回rejected
promise状态转变的两个过程:
1.pending -> resolve
2.pending -> reject
promise的.then和.catch方法:
1、Promise的状态一经改变就不能再改变
2、.then和.catch方法都会返回一个新的Promise对象
3、.catch方法不管被连接到哪里,都能捕获上层未被捕捉过的错误
4、在Promise中,返回任意一个非promise的值都会被包裹成promise对象,例如return 2会被包装为return Promise.resolve(2)
5、Promise的.then和.catch可以被多次调用,但是如果Promise内部的状态一经改变,并且有了一个值,那么后续每次调用.then或者.catch的时候都会直接拿到该值
6、.then或者.catch中return一个error对象并不会抛出错误,所以不会被后续的.catch捕捉
7、.then或者.catch返回的值不能是该promise本身,否则会造成死循环
8、.then或者.catch的参数期望是函数,传入非函数则会发生值透传
9、.then方法是能接收两个参数的,一个是处理成功的函数resolve,一个是处理失败的函数reject,在某些时候可以认为.catch是.then的第二个参数的简便写法
promise的.finally方法:
1、.finally方法也是返回一个Promise对象,它在Promise结束的时候,无论结果为resolved还是rejected,都会执行里面的回调函数
2、.finally方法的回调函数不接收任何的参数,也就是说我们在.finally函数里面是没法知道Promise最终的状态是resolved还是rejected的
3、.finally最终返回的默认会是一个“上一次的Promise对象值”,不过如果抛出的是一个异常则返回异常的Promise对象
promise的.all和.race方法:
1、Promise.all()方法是接收一组异步任务(数组形式的参数),然后并行执行异步任务,只有在所有异步操作都成功执行(resolve)之后才执行回调函数
2、.race()方法也是接收一组异步任务,然后并行执行异步任务,只保留第一个执行完成的异步操作的结果,其他方法仍然在执行,不过执行结果会被抛弃
3、Promise.all().then()结果中数组的顺序和Promise.all()接收到的数组顺序一致
4、.all()和.race()传入的数组中如果有会抛出异常的异步任务,那么只有最先抛出的错误会被捕获,并且是被.then()的第二个参数reject或者后面的.catch()捕获,但是并不会影响数组中后续其他的异步任务的继续执行
Promise.all中如果有一个抛出异常了会如何处理:
.all和.race传入的数组中如果有会抛出异常的异步任务,那么只有最先抛出的错误会被捕获,并且是被.then的第二个参数或者后面的.catch捕获;但并不会影响数组中其它的异步任务的执行。
Promise可以链式调用的原因:
由于它的.then、.catch、.finally方法都会返回一个全新的Promise对象,所以可以允许我们链式调用
async与await
async 是异步的意思,await则可以理解为等待
放到一起可以理解async就是用来声明一个异步方法,而 await是用来等待异步方法执行
async
async函数返回一个promise对象,下面两种方法是等效的
function f() {
return Promise.resolve('TEST');
}
// asyncF is equivalent to f!
async function asyncF() {
return 'TEST';
}
复制代码
await
正常情况下,await命令后面是一个 Promise对象,返回该对象的结果。如果不是 Promise对象,就直接返回对应的值
async function f(){
// 等同于
// return 123
return await 123
}
f().then(v => console.log(v)) // 123
复制代码
不管await后面跟着的是什么,await都会阻塞后面的代码
async function fn1 (){
console.log(1)
await fn2()
console.log(2) // 阻塞
}
async function fn2 (){
console.log('fn2')
}
fn1()
console.log(3)
复制代码
上面的例子中,await 会阻塞下面的代码(即加入微任务队列),先执行 async外面的同步代码,同步代码执行完,再回到 async 函数中,再执行之前阻塞的代码
所以上述输出结果的顺序为:1 fn 3 2
综合练习:
//练习1
setTimeout(()=>{ // 宏任务
console.log("a")
},0)
new Promise((resolve)=>{
resolve() // 同步的
console.log("b") // 同步的
}).then(()=>{ // 从这里开始,到下面
console.log("c") // 上一次resolve执行触发then里面的操作
Promise.resolve().then(()=>{ // 这里的已经是resolve状态,then操作立马触发
console.log("e") // e在c之后立马执行
}).then(()=>{
console.log("f") // f在e之后立马执行
})
}) // 接上面,到这里都是微任务,注意这里的整个then操作中包裹的都是微任务
console.log("d")
复制代码
上面执行后返回的结果顺序是:b d c e f a
//练习2
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(function () {
console.log('settimeout')
})
async1()
new Promise(function (resolve) {
console.log('promise1')
resolve()
}).then(function () {
console.log('promise2')
})
console.log('script end')
复制代码
分析过程:
- 执行整段代码,遇到
console.log('script start')直接打印结果,输出script start - 遇到定时器了,它是宏任务,先放着不执行
- 遇到
async1(),执行async1函数,先打印async1 start,下面遇到await怎么办?先执行async2,打印async2,然后阻塞下面代码(即加入微任务列表),跳出去执行同步代码 - 跳到
new Promise这里,直接执行,打印promise1,下面遇到.then(),它是微任务,放到微任务列表等待执行 - 最后一行直接打印
script end,现在同步代码执行完了,开始执行微任务,即await下面的代码,打印async1 end - 继续执行下一个微任务,即执行
then的回调,打印promise2 - 上一个宏任务所有事都做完了,开始下一个宏任务,就是定时器,打印
settimeout
所以最后的结果是:script start、async1 start、async2、promise1、script end、async1 end、promise2、settimeout
Node的核心概念
非阻塞I/O:
访问磁盘和网络这样的I/O 请求会比较慢,所以我们希望,在读取文件或通过网络发送消息时,运行平台不会阻塞业务逻辑的执行。
Node 用三种技术来解决这个问题:事件、异步API、非阻塞I/O。
非阻塞I/O 是个底层术语。它的意思是说,你的程序可以在做其他事情时发起一个请求来获取网络资源,然后当网络操作完成时,将会运行一个回调函数来处理这个操作的结果。

同步式I/O是指: 线程在执行中如果遇到磁盘读写或网络通信(统称为 I/O 操作),通常要耗费较长的时间,这时操作系统会剥夺这个线程的 CPU 控制权,使其暂停执行,同时将资源让给其他的工作线程,这种线程调度方式称为阻塞 。
当 I/O 操作完毕时,操作系统将这个线程的阻塞状态解除,恢复其对CPU的控制权,令其继续执行。
这种 I/O 模式就是通常的同步式 I/O(Synchronous I/O)或阻塞式 I/O (Blocking I/O)。
多线程同步式I/O如下图:

异步式 I/O (Asynchronous I/O)或非阻塞式 I/O (Non-blocking I/O)则针对所有 I/O 操作不采用阻塞的策略。
当线程遇到 I/O 操作时,不会以阻塞的方式等待 I/O 操作的完成或数据的返回,而只是将 I/O 请求发送给操作系统,继续执行下一条语句。
当操作系统完成 I/O 操作时,以事件的形式通知执行 I/O 操作的线程,线程会在特定时候处理这个事件。
为了处理异步 I/O,线程必须有事件循环,不断地检查有没有未处理的事件,依次予以处理。
单线程异步式I/O如下图:

同步式I/O与异步式I/O比较
简而言之,异步式 I/O 就是少了多线程的开销。
对操作系统来说,创建一个线程的代价是十分昂贵的,需要给它分配内存、列入调度,同时在线程切换的时候还要执行内存换页,CPU 的缓存被清空,切换回来的时候还要重新从内存中读取信息,破坏了数据的局部性。

npm的基本用法
npm就是一个网站,里面存放着各种node需要用到的插件,可以使用npm的指令进行下载。
npm的基本指令集:
npm init:初始化项目,下图

package.json中的内容:下图

npm install packagename:安装模块不指定版本号 默认会安装最新的版本,其中packagename是你需要安装的包的对应名称,下图

npm install packagename@0.0.1:安装指定版本的模块,如npm install express@4.17.0,就是安装4.17.0版本的express,下图

安装之后,如何使用?使用require引入express:下图

npm install packagename -g 或 --global:安装全局的模块(不加参数的时候默认安装本地模块)
npm install packagename --save 或 -S:--save、-S参数意思是把模块的版本信息保存到dependencies(生产环境依赖)中,即你的package.json文件的dependencies字段中
npm install packagename --save-dev 或 -D:--save-dev 、 -D参数意思是吧模块版本信息保存到devDependencies(开发环境依赖)中,即你的package.json文件的devDependencies字段中,下图

npm uninstall packagename [options]:卸载已经安装的模块,后面的options参数意思与安装时候的意思一样,与这个命令相同的还有npm remove 、npm rm、npm r 、 npm un 、 npm unlink 这几个命令功能和npm uninstall基本一样
npm outdated:这个命令会列出所有已经过时了的模块
npm update [-g]:对于已经过时了的模块可以使用上面的命令去更新
npm update [包名称]:更新指定名称的包





















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)