Node.js相关知识
Node.js 是什么?
- Node.js 是一个 JavaScript 运行时环境,可以解析和执行 js 代码。
- 构建于 Chrome 的 V8 引擎之上
- 没有 BOM、DOM,有 EcmaScript 语法。
- node 中有很多具名的核心模块
- fs 文件操作模块
- http 服务器构建模块
- path 路径模块
- os 操作系统信息模块
- 在核心模块中提供了一些服务器级别的操作 API - 文件读写 - 网络服务的构建 - 网络通信 - http 服务器
node 都有哪些特性?
单线程
- 不会为每个用户连接创建一个新的线程,仅仅使用一个线程,减少了操作系统的线程创建
和销毁的时间开销。缺点就是一个用户造成线程的崩溃会导致整个服务的崩溃。 - 减少内存的开销
- 不会为每个用户连接创建一个新的线程,仅仅使用一个线程,减少了操作系统的线程创建
事件驱动 event-driven
- node 中一个时刻只能执行一个事件回调函数,但是执行过程中,可以转而处理
其他事件,然后返回继续执行原事件的回调函数,这种处理机制,称为“事件环”机制。
- node 中一个时刻只能执行一个事件回调函数,但是执行过程中,可以转而处理
非阻塞 I/O
- I/O 数据传输操作会阻塞代码的执行,极大降低了程序的执行效率,因为一个线程只能处理
一项任务,要想提高吞吐量必须通过多线程。非阻塞 I/O 机制,可以将异步操作的处理
代码放在回调函数中,从而提高了程序的执行效率。
- I/O 数据传输操作会阻塞代码的执行,极大降低了程序的执行效率,因为一个线程只能处理
浏览器的进程和线程
- 一个程序可以有多个进程
- 一个进程可以有多个线程
- 进程在执行应用程序中拥有独立的内存单元,而多个线程共享内存。
- 多个线程之间可以相互通信
- 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口
- 线程不能独立执行,必须依存在应用程序中
Node.js 适合开发什么?
- 善于 I/O,不善于计算,因为 Node.js 最擅长的就是任务调度,不适合于利用 CPU 进行过多的运算的程序。
- 当应用程序需要处理大量并发的 I/O,而在向客户端发出响应之前,应用程序内部不需要
进行非常复杂处理的时候,Node.js 非常合适。 - Node.js 也非常适合与 web socket 配合,开发长连接的实时交互应用程序。
- 用户表单
- 考试系统
- 聊天室
- 图文直播
nodejs 能做什么?
- Node.js 可以生成动态页面内容
- Node.js 可以创建,打开,读取,写入,删除和关闭服务器上的文件
- Node.js 可以收集表单数据
- Node.js 可以添加,删除,修改数据库中的数据
服务端渲染和客户端渲染的区别
- 客户端渲染不利于 SEO 搜索引擎优化
- 服务器渲染可以被爬虫抓取
- 例如:京东商品列表是服务端渲染,用户评论是客户端渲染(提高用户体验)
小补充:使用 cnpm
方法一 安装 cnpm
npm install --global cnpm
方法二 改变 registry
npm install jquery --registry=https://registry.npm.taobao.org
方法三 加入配置选项
npm config set registry https://registry.npm.taobao.org
npm config list
用 nodejs 实现读取文件操作
const fs = require("fs")
//fs 核心模块提供了一个fs.readFile方法,用来读取指定目录下的文件
//fs.readFile有三个参数
// 1. 读取文件的路径
// 2. 读取文件的编码格式
// 3. 当文件读取完成,调用这个callback回调函数来读取文件的结果
fs.readFile('./data/hello.txt','utf-8',function(err,data){
if(err){
console.log(err) //第一个参数是err对象
return
} else {
console.log(data) //第二个参数才是data数据
}
})
用 nodejs 实现写入文件操作
const fs = require('fs')
let msg = 'hello world'
//fs.writeFile有三个参数
// 1. 第一个参数为写入的文件路径
// 2. 第二个参数为写入的内容
// 3. 第三个参数为可选参数,表示写文件的编码格式
// 4. 第四个参数为回调函数,回调函数只有一个参数err,判断是否写入成功。
fs.writeFile('./data/hello.txt',msg,'utf-8',function(err){
if(err){
console.log('写入错误' + err)
} else {
console.log('ok')
}
})
nodejs 如何开启进程,进程如何通讯?
进程 process VS 线程 thread
- 进程: 进行资源分配和调度的最小单元,有独立内存空间
- 线程: 进行运算调度的最小单元,共享进程内存空间
- js 是单线程的,但可以多进行执行,如 、WebWorker
为何需要多进程?
- 多核 CPU,更适合处理多进程
- 内存较大,多个进程才能更好的利用(单进程有内存上线)
开启进程两种方法 child_process.fork, cluster.fork
1 | // parent.js |
1 | // compute.js |
1 | const http = require('http'); |
CommonJS 解析
CommonJS 的核心思想是通过 require 方法来同步加载依赖的其他模块,通过 module.export 来导出需要暴露的接口
require 内部逻辑:
例如:require(X)
- 如果 X 是内置模块(比如 require(‘http’))
a. 返回该模块
b. 不再继续执行 - 如果 X 以 ‘./‘或者 ‘../‘开头
a. 根据 X 所在父模块,确定 X 的绝对路径
b. 将 X 当作文件,依次查找以下文件(.x |.x.js | .x.json | .x.node),只要一个存在就返回该文件,不再继续执行
c. 把 X 当作目录,依次查找以下文件(.x/package.json | .x/index.js | .x/index.json | .x/index.node),只要一个存在就返回并不再执行 - 如果 X 不带路径
a. 根据 X 所在父模块,确定 X 可能的安装目录,依次往上级目录查找,把 X 当成文件名或目录名加载 - 找不到抛错’not found’