Node.js
是一个基于事件驱动、非阻塞I/O的Web服务器,采用Chrome V8
引擎, node.js
具有异步I/O处理, 事件与回调函数, 单线程, 跨平台等特点. 优点: 高并发, 适合I/O密集型应用, 缺点: 不适合CPU密集型应用.
node安装
nodejs下载 注:windows 下载后缀为 .msi mac 下载后缀为 .pkg
命令行运行node.js文件 node 文件路径
node特点
- 主线程是单线程(异步)
callback
,将后续的逻辑写成函数,传入当前执行的函数中,当执行的函数
得到结果后,执行传入的函数(回调函数) web
中的异步setTimeout
callback
onclick
ajax
i/o操作
读写操作, 异步读写event-driven
事件驱动(发布订阅)
nodejs基础篇
- 全局对象
global
类似浏览器全局对象window
,但node
环境中没有window
- console对象
console.log()
,console.error()
,console.warn()
等 - __dirname 当前文件(模块)所在目录
- __filename 当前文件(模块)的文件名称(包含文件绝对路径)
全局变量 可以不声明直接使用
- console
- process 进程 设置环境变量 process.env process.nextTick()异步
- Buffer 缓冲区
模块化
模块化 用来模块化用来分割,组织和打包软件。每个模块完成一个特定的子功能,所有的模块按某种方法组装起来,成为一个整体,完成整个系统所要求的功能
模块化系统 1. 定义模块 2. 模块导入(依赖) 3.模块导出
- 一个文件就是一个独立的模块
- 模块加载采用同步模式
- 通过require函数导入, exports对象导出
模块
- 在node中,文件和模块都是一一对应的的,也就是一个文件就是一个模块,每个模块都有自己的作用域
,我们通过var声明的变量并非全局而是该模块作用域下的, 外部不能直接访问 - 模块的加载和使用 require(‘模块’) 模块的路径可以是绝对路径(/a.js)也可以是相对路径(./a.js)
模块路径如果没有以/或者./开头,那么这个模块要么是核心模块 要么是node_modules文件夹下
- 模块加载机制
文件名称 -> .js -> .json -> .node
- 首先按照加载的模块的文件名称进行查找
- 如果没有找到,则会在文件名称后加上.js的后缀,进行查找
- 如果还没有找到,则会在文件名称后加上.json后缀,进行查找
- 如果还没有,则会在文件名称后加上.node的后缀,进行查找
- 最后还是没找到则会报错 Cannot find module ‘./est’`
- 如果我们想一个模块能够访问另外一个模块定义的变量,可以用以下方法
- 把变量作为global对象的一个属性值,但是这样的做法不推荐(污染全局变量)
- 使用模块对象module下的exports对象将模块中的局部变量对外提供访问
- module.exports === exports 但不要为他们重新赋值
- 导出 module.exports = xxx
- 导入 require(‘xxx’)
1
2
3
4// tew/a.js tew/b.js
require('b.js') // a.js 引入文件 b.js
// tew/index.js
require('./tew') // 引入文件夹时可简写 等同于 require('./tew/index.js')
Event(事件)
事件是整个 Node.js 的核心,Node.js中大部分模块都使用或继承了该模块(类似 WebAPI 中的EventTarget) 使用: require(‘event’)
1 | EventEmitter 类 |
Process(进程)
process 对象是一个全局变量,它提供当前 Node.js 进程的有关信息,以及控制当前 Node.js 进程, 作为一个全局变量, 无需使用 require()
process.argv 属性返回一个数组,其中包含当启动 Node.js 进程时传入的命令行参数。 第一个元素是 process.execPath。 第二个元素将是正在执行的 JavaScript 文件的路径。 其余元素将是任何其他命令行参数。
1
2
3
4
5
6
7
8console.log(process.argv)
// node process app -i
[
'C:\\Program Files\\nodejs\\node.exe', // 执行路劲
'C:\\Users\\Administrator\\Desktop\\tew\\process', // 文件路径
'app', // 命令行参数
'-i' // 命令行参数
]process.env 属性返回包含用户环境的对象, 如获取或设置node运行的环境变量
- process.exit() 可以用来立即退出进程。即使当前有操作没执行完
- process.cwd() 当前的工作目录
- process.stdin或process.stdout 进程的标准输入、标准输出
1
2
3
4
5
6process.stdout.write('请输入你要创建的项目名称:')
process.stdin.on('data', (e) => {
fs.mkdirSync(e.toString().replace('\r\n', ''))
process.stdout.write('项目创建成功')
process.exit()
})
Buffer
用于操作二进制数据的类 类似数组 长度固定 只能操作二进制数据
1
2
3
4
5
6
7
8
9
10 // 创建
const buf1 = Buffer.alloc(10)
const buf2 = Buffer.from('buffer')
const buf3 = Buffer.from([1,2,3])
// 写入
buf1.write('hello')
// 读取
console.log(buf1.toSring())
// 合并
Buffer.concat([buf1, buf3])
通过长度定义
1
2
3
4
5var buffer = Buffer.alloc(6)
console.log(buffer) // <Buffer 00 00 00 00 00 00>
var buffer = Buffer.allocUnsafe(6)
console.log(buffer) // <Buffer 00 00 00 00 4f 00>
console.log(buffer.length) // 6通过数组定义
1
2
3var buffer = Buffer.from('阿萨达')
console.log(buffer) // <Buffer e9 98 bf e8 90 a8 e8 be be>
console.log(buffer.length) // 9字符串创建
1
2
3var buffer = Buffer.from([1, 'a', '阿'])
console.log(buffer) // <Buffer 01 00 00>
console.log(buffer.length) // 3常用buffer方法
- buffer.fill() 填充buffer中的内容
- buffer.toString() 将buffer转化为字符串
- buffer.slice() 截取想要的buffer
- buffer.copy() 拷贝buffer
- buffer.concat() 拼接buffer
- buffer.isBuffer() 判断是否是buffer类型
FileSysterm
fs模块提供了一些与文件系统进行交互的 API,使用需要引入require(‘fs’),fs中的方法都是由同步和异步组成
- 写入数据到文件 fs.writeFileSync(file, data[, options], callback)
- 文件追加内容 fs.appendFileSync(‘./1.txt’, ‘ 我是追加的内容’)
- 读取文件内容 content = fs.readFileSync(‘./1.txt’)
- 获取文件其他信息 info = fs.statSync(‘./1.txt’)
常用: info.size 文件大小 info.isFile() 是否是文件 info.isDirectory() 是否是目录
- 删除文件 fs.unlinkSync(‘1.txt’)
- 判断文件、目录是否存在 fs.existsSync(‘./yn’)
- 创建目录 不会进行递归创建 fs.mkdirSync(‘./yn’)
- 删除目录 fs.rmdirSync(‘./yn’);
读取目录 files = fs.readdirSync(‘../node’)
文件操作时最好将路径使用path.resovle或path.join转化 且路径中不能有中文否则会报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35// 递归删除文件及目录
function rmAll(dirPath) {
if (fs.existsSync(dirPath)) { // 路径或文件是否存在
let state = fs.statSync(dirPath) //读取路径或文件属性
if (state.isDirectory()) { // 是目录
let files = fs.readdirSync(dirPath) //路径信息
files.forEach( child => {
rmAll(path.join(dirPath, child))
})
fs.rmdirSync(dirPath) // 删除文件夹
} else if(state.isFile()){ // 是文件
fs.unlinkSync(dirPath)
}
} else {
console.log('该文件或文件夹不存在')
}
}
rmAll('./yn')
// 遍历文件
function readFile(dirPath) {
if (fs.existsSync(dirPath)) { // 路径或文件是否存在
let state = fs.statSync(dirPath) //读取路径或文件属性
if (state.isDirectory()) { // 是目录
let files = fs.readdirSync(dirPath) //路径信息
files.forEach(child=> {
readFile(path.join(dirPath, child))
})
} else if(state.isFile()){ // 是文件
console.log(dirPath)
}
} else {
console.log('该文件或文件夹不存在')
}
}
readFile('../')更多node文件操作请查看 Node.js 中文网
核心对象path
- 引入path
const path = require('path')
- 拼接路径
path.join(__dirname,'a','b')
c:tew/a/b - 相对路径转绝对路径
path.resovle('./xxx')
- 接收一个合法的路径字符串,转换成一个对象
let pathObj = path.parse(mypath)
- 接收一个路径对象,转换成一个字符串路径
let str = path.format(pathObj)
- 取文件后缀名
path.extname('1.js')
stream流
1 | const rs = fs.createReadStream('./conf.js') |