Node 学习(一) 初识Nodejs

Posted on 2019-08-25 15:24  lc_博客  阅读(129)  评论(0)    收藏  举报

前言:前端时间开始正式接触Node,因为之前只是使用过 nwjs 跟 webpack 等基于Node开发的工具,想进一步深入Node,为了避免学过之后又忘了(是的,看过一遍之后又忘得7788了),所以记下笔记。

Nodejs 是基于Chrome V8引擎开发的能使JavaScript在服务器端运行的运行时环境。基于 js 引擎的单线程特性,所以Nodejs 默认也是单进程单线程的。为什么一个单进程单线程的语言(暂时就叫Nodejs为一门语言),会这么受欢迎呢?

1. Node 是基于事件驱动的异步IO架构。以读取文件为列,当Node接收到一个读取文件的请求之后,通过调用内置模块 fs.readFile() 这个 API 去读取文件

1 fs.readFile(path, (err, data) => {
2    // 读取文件完成之后的回调 
3 })

当调用 fs.readFile() 的时候,会去通知 Node 底层进行文件读取,但是不会关心文件什么时候读取完成,通知完之后就会接着执行下面的js 逻辑,当底层操作完文件之后,会通过回调的方式调用 fs.readFile() 的第二个参数也就是回调函数,通知js 文件操作完成。

2. 单线程。单线程有一个好处,就是不需要去管理多线程之间的状态,也不会出现死锁,也不会有线程创建销毁切换的开销。单线程 + 异步IO + 事件驱动 使得 Node 可以处理海量网络请求。但是单线程应用同时也是有自己的一些弱点的,比如:

  1). 无法充分发挥多核CPU的特点

  2). 一旦出现错误,会导致整个Node服务的退出,这一点是致命的

  3). 当出现需要长时间占用CPU的操作比如耗时的计算,会导致CPU一直被占用,其他的请求/回调 无法及时处理。这一点跟浏览器的js类似,浏览器的js线程跟UI渲染线程是互斥的,当其中一个需要长时间执行的话,就会导致另一个无法及时处理

但是Node设计的时候也有考虑到这个问题,类似H5的web-worker,Node也有对应的API来衍生子进程以处理应用健壮性以及充分利用CPU问题:child_process 跟 cluster。对于这两个API,后续会进一步研究。

3. 回调。js的一大亮点就是回调。正常情况下程序都是从上往下执行的,也就是我们常说的同步。但是js可以在执行某一个请求的时候,提供一个回调函数,然后不用等待请求完成,继续执行下面的逻辑。当请求执行完成的时候,会自动将该回调函数放入事件循环队列里面,等待主线程的调用。这一步不需要我们做任何处理。

 

Node 应用场景

1. 因为Node是基于事件驱动的异步架构,通过事件驱动来服务IO的,所以对于IO密集型的应用,Node是非常适用的。

2. 对于CPU密集型的应用,是否就不适用呢?CPU密集型应用带来的问题主要是会长时间占用CPU,会导致后面的请求或者IO回调函数处于阻塞状态。但是Node提供了 child_process 可用于创建子进程并可以跟主进程进行消息交互。子进程也解决了Node无法充分利用CPU的问题。所以对于CPU密集型应用,Node也可以说是适用的,主要的问题是如何处理大量运算问题。

注意:Node js 引擎是单线程,但并不意味着Node是单线程,它的底层是 C/C++ 去处理IO任务的,这里也会通过创建多个线程去执行。只是这里不需要我们去操作,它是由系统内核完成的。