前置概念
CPU密集
进行的一些压缩,解压,加密,解密等计算都属于CPU密集
I/O密集
文件的读取,网络操作,数据库等操作时,为I/O密集
高并发
单位时间内的访问量
进程
是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位
NodeJS工作模型
image.png此时,NodeJS可以处理很多用户发来的一些请求,而这写请求不会因为调用I/O操作而空闲,也就是非阻塞I/O,CPU可以不停的进行接收请求,并进行I/O操作,而I/O操作则是多线程的,当I/O操作完成后,CPU再讲数据返回给客户端.NodeJS解决了CPU上的空闲和处理高并发的能力
线程
进程内一个相对独立的,可调度的执行单元,与同属一个进程的线程共享进程的资源
多线程
启动一个进程,在一个进程内启动多个线程,这样,多个线程也可以一块执行多个任务
NodeJS单线程
单线程只是针对主进程,I/O操作系统底层多线程调度. 单线程并不是单进程
环境
CommonJS
每个文件是一个模块,有自己的作用域
在模块内部module变量代表模块本身
module.exports属性代表模块对外接口
require 规则
- / 表示绝对路径,./表示相对于当前文件的路径
- 支持js,json,node扩展名,不写一次尝试
- 不写路径则认为是build-in模块或者各级node_modules内的第三方模块
require 特性
- module被加载的时候执行,加载后缓存
- 一旦出现某个模块被循环加载,就只输出已经执行的部分,还未执行的部分不会输出
module.exports与exports的区别
const exports = module.exports // exports就是module.exports的简写
(
function(exports, require, module, __filename, __dirname) {
// code
}
)
exports.test = 100
exports = {
a: 1,
b: 2
}
如果写成exports,那么exports的指向就会被改变,它不再指向module.exports,也就什么都没有输出
因此:
module.exports = {
a: 1,
b: 2
}
此时,module.exports将指向了这个对象,即输出了这个对象
模块对外的输出永远是module.exports,你可以添加它的属性,但是你不能修改它的指向,如果exports的指向被修改,那么它将不会对外输出
global
- CommonJS
- Buffer,process,console
- timer
// mod1
global.test = 100
// mod2
console.log(test) // 100
process
const {argv, argv0, execArgv, execPath} = process
// argv 启动这个process的时候的所有参数
// argv0 保存了argv这个数组的引用
// execArgv 调用node所调用的特殊参数
// execPath argv的第一个参数
argv.forEach(item => {
console.log(item)
})
const {env} = process
console.log(env) // 执行环境
console.log(process.cwd()) // 当前命令所执行的路径
setImmediate(() => {
console.log('setImmediate')
})
setTimeout(() => {
console.log('setTimeout')
}, 0);
process.nextTick(() => {
console.log('nextTick')
})
nextTick是将其放在了当前队列的队尾,而setImmediate是放在了下一个队列的队尾,setTimeout是放在两者之间
基础API
normalaize
处理路径
const {normalize} = require('path')
console.log(normalize('/usr//local/bin'))
join
拼接路径
const {join} = require('path')
console.log(join('/usr', 'local', 'bin/'))
resolve
相对路径解析为绝对路径
const {resolve} = require('path')
console.log(resolve('./'))
basename dirname extname
const {basename, dirname, extname} = require('path')
const filePath = '/usr/local/bin/no.txt'
console.log(basename(filePath)) // 文件名
console.log(dirname(filePath)) // 路径
console.log(extname(filePath)) // 扩展名
parse format
分析路径
const {parse, format} = require('path')
const filePath = '/usr/local/include'
const ret = parse(filePath)
console.log(ret)
console.log(format(ret)) // 将拆分的路径执行回来
输出
{ root: '/',
dir: '/usr/local',
base: 'include',
ext: '',
name: 'include' }
sep delimiter win32 posix
和操作系统相关的一些东西
const {sep, delimiter, win32, posix} = require('path')
console.log('sep:', sep) // 路径分隔符 /
console.log('win sep', win32.sep) // \
console.log('PATH:', process.env.PATH)
// PATH: /Library/Frameworks/Python.framework/Versions/3.6/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
console.log('delimiter:', delimiter) // :
console.log('win delimiter:', delimiter) // :
总结
__dirname,__filename 总是返回文件的绝对路径
process.cwd()总是返回执行node命令所在文件夹
Buffer
处理二进制数据流 实例类似整数数组,大小固定
console.log(Buffer.alloc(10))
console.log(Buffer.alloc(5, 1))
console.log(Buffer.allocUnsafe(5,1))
console.log(Buffer.from([1,2,3]))
console.log(Buffer.from('test'))
<Buffer 00 00 00 00 00 00 00 00 00 00>
<Buffer 01 01 01 01 01>
<Buffer 18 e3 04 04 01>
<Buffer 01 02 03>
<Buffer 74 65 73 74>
console.log(Buffer.byteLength('test')) // 字节长度
console.log(Buffer.byteLength('测试'))
console.log(Buffer.isBuffer({})) // false
console.log(Buffer.isBuffer(Buffer.from([1, 2, 3]))) // true
const buf1 = Buffer.from('h')
const buf2 = Buffer.from('e')
const buf3 = Buffer.from('l')
const buf4 = Buffer.from('l')
const buf5 = Buffer.from('o')
const buf = Buffer.concat([buf1, buf2, buf3, buf4, buf5])
console.log(buf) // 连接buffer
const buf = Buffer.from('this is a test')
/* buf.length
buf.toString()
buf.fill() // 填充
buf.equals()
buf.indexOf()
buf.copy() */
events
const EventEmitter = require('events')
class CustomEvent extends EventEmitter {
}
const ce = new CustomEvent()
ce.on('test', () => {
console.log('this is a test')
})
setInterval(() => {
ce.emit('test')
}, 500)
const EventEmitter = require('events')
class CustomEvent extends EventEmitter{}
const ce = new CustomEvent()
ce.on('error', err => {
console.log(err)
})
ce.emit('error', new Error('oops'))
执行一次
import { setInterval } from 'timers';
const EventEmitter = require('events')
class CustomEvent extends EventEmitter{}
const ce = new CustomEvent()
ce.once('test', () => {
console.log('test event')
})
setInterval(() => {
ce.emit('test')
}, 500)
移除
const EventEmitter = require('events')
class CustomEvent extends EventEmitter{}
const ce = new CustomEvent()
function fn1() {
console.log('fn1')
}
ce.on('test', fn1)
ce.on('test', fn2)
setInterval(() => {
ce.emit('test')
}, 500)
setTimeout(() => {
ce.removeListener('test', fn2)
}, 1500);
fs
读文件
const fs = require('fs')
fs.readFile('./module2.js','utf8', (err, data) => {
if (err) throw err
console.log(data)
})
同步操作
const data = fs.readFileSync('./module1.js', 'utf8')
console.log(data)
写文件
const fs = require('fs')
fs.writeFile('./text', 'this is a test', {
encoding: 'utf8'
}, err => {
if(err) throw err
console.log('done')
})
查看文件状态
const fs = require('fs')
fs.stat('./fs.js', (err, stats) => {
if(err) throw err
console.log(stats.isFile())
console.log(stats.isDirectory())
console.log(stats)
})
重命名
const fs = require('fs')
fs.rename('./text', 'text.txt', err => {
if (err) throw err
})
打印目录的文件名
const fs = require('fs')
fs.readdir('../', (err, files) => {
if (err) throw err
console.log(files)
})
删除文件夹
const fs = require('fs')
fs.rmdir('./text', err => {
if(err) throw err
})
监视文件或目录的变化
网友评论