在 Node 中有一个轻量级的process.nextTick()异步方法,它是在当前事件队列结束时调用,setImmediate()是当前 Node Event Loop 结束时立即执行,那执行顺序有什么区别呢?
下面举例说明process.nextTick(fn)与setImmediate(fn)与setTimeout(fn,0)之间的区别:
// timer.js setImmediate(()=>{ console.log("setImmediate")});setTimeout(()=>{ console.log("setTimeout 0")},0);setTimeout(()=>{ console.log("setTimeout 100")},100);process.nextTick(()=>{ console.log("nextTick") process.nextTick(()=>{ console.log("nextTick inner") })});看下执行结果:
$ node timer.js nextTicknextTick innersetTimeout 0setImmediatesetTimeout 100process.nextTick()中的回调函数最快执行,因为它将异步事件插入到当前执行队列的末尾,但如果process.nextTick()中的事件执行时间过长,后面的异步事件就被延迟 。
setImmediate()执行最慢,因为它将事件插入到下一个事件队列的队首,不会影响当前事件队列的执行 。当setTimeout(fn, 0)是在setImmediate()之前执行 。
2.4 Buffer 二进制
Buffer 对象用于处理二进制数据流 。JS 没有处理二进制的功能,而 Node 中的一部分代码是由 C++ 实现的,所有 Node 中的 Buffer 性能部分用 C++ 实现,非性能部分由 JS 封装 。
Buffer 实例类似整数数组,元素为十六进制的两位数(0~255),并且挂载在 global 对象上不需要 require就能使用 。
最新的 Buffer API 使用Buffer.alloc(length, value)创建固定长度为 length 的 Buffer 实例,value 默认填充 0,使用Buffer.from()将其它类型数据转为 Buffer:
console.log(Buffer.alloc(5)) // <Buffer 00 00 00 00 00>console.log(Buffer.alloc(5, 44)) // <Buffer 2c 2c 2c 2c 2c>console.log(Buffer.from([3, 4, 5])) // <Buffer 03 04 05>console.log(Buffer.from('test')) // <Buffer 74 65 73 74>console.log(Buffer.from('测试')) // <Buffer e6 b5 8b e8 af 95>注意到字符串转 Buffer 时英文占一位,中文占三位,而不是四位,当中文乱码的时可以考虑没有正确读取 Buffer 流 。
Buffer 类提供几个静态方法,Buffer.byteLength()计算长度,Buffer.isBuffer()做验证,Buffer.concat()拼接 Buffer 实例:
const buf1 = Buffer.from([3, 4, 5])const buf2 = Buffer.from('test')console.log(Buffer.byteLength('test')) // 4console.log(Buffer.byteLength('测试')) // 6 console.log(Buffer.isBuffer('test')) // falseconsole.log(Buffer.isBuffer(buf1)) // trueconsole.log(Buffer.concat([buf1, buf2])) // <Buffer 03 04 05 74 65 73 74>除此之外,Buffer 实例也有常用的属性和方法,类似 JS 中的 String,有length、toString('base64')、equals()、indexOf()等 。
三、基础 API3.1 path 路径相关
path 是处理和路径相关问题的内置 API,可以直接require('path')使用 。以下示例常用的 path 方法 。
对路径的处理常用path.normalize()规范路径、path.join()拼接路径,以及使用path.resolve()将相对路径解析为绝对路径:
const path = require('path')console.log( path.normalize('//asd/das'), // /asd/das path.join('user', 'local'), // user/local path.resolve('./')) // /Users/Documents/webProjects/testNode/apiTest解析某个路径,可以用path.basename()得到文件名称,path.extname()得到后缀扩展名,path.dirname()得到目录名:
【NodeJS常用 API 整理】const path = require('path')const filePath = 'webProjects/testNode/apiTest/path.js'console.log( path.basename(filePath), // path.jspath.extname(filePath) // .jspath.dirname(filePath), // webProjects/testNode/apiTest)以上解析路径方法得到某个值,还可以使用path.parse()完全解析路径为一个对象,path.format()反向操作:
let sp = path.parse(filePath)console.log(sp)// { root: '',// dir: 'webProjects/testNode/apiTest',// base: 'path.js',// ext: '.js',// name: 'path' }console.log(path.format(sp))// webProjects/testNode/apiTest/path.js除此之外,还有对于系统路径的操作,使用path.sep取得路径分隔符,路径片段分隔符,POSIX 上是/, windows 上是,path.delimiter取得系统路径定界符,POSIX 上是:,Windows 上是;,示例如下:
console.log(filePath.split(path.sep)) // [ 'webProjects', 'testNode', 'apiTest', 'path.js' ]console.log(process.env.PATH) // 系统路径配置// /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbinconsole.log(process.env.PATH.split(path.delimiter))// [ '/usr/local/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin' ]以上就是 Node 对路径的常用操作,需要注意的是,在获取路径时有几种方式,得到的路径是不同的:
推荐阅读
- 几项措施,让你的api不再裸奔
- ROS 的常用命令行工具
- 红茶常用外形评语,喝红茶的好处介绍
- excel常用的趋势分析图,值得收藏
- 小程序的api是什么
- Linux操作系统:文件的逻辑组织
- CNN中常用的四种卷积详解
- 红茶审评常用术语,评茶滋味术语
- API设计的几条原则
- JAVA程序员常用的几个工具类
