一、Debug 调试方法

Node 的调试方法有很多,主要分为安装 node-inspect 包调试、用 Chrome DevTools 调试和 IDE 调试,可以在官网的 Docs Debugging Guide 查看安装方法。

下面介绍使用 Chrome DevTools 调试的方法,首先安装 Chrome Extension NIM,打开 Inspect 入口页面 chrome://inspect

写一个简单 debug.js 测试文件:

// apiTest/debug.js
console.log("this is debug test")
function test () {console.log("hello world")
}
test()
复制代码

使用node --inspect-brk来启动脚本,-brk相当于在程序入口前加一个断点,使得程序会在执行前停下来

$ node --inspect-brk apiTest/debug.js
Debugger listening on ws://127.0.0.1:9229/44b5d11e-3261-4090-a18c-2d811486fd0a
For help, see: https://nodejs.org/en/docs/inspector
复制代码

在 chrome://inspect 中设置监听端口 9229(默认),就可以看到可以 debug 的页面:

(function (exports, require, module, __filename, __dirname) {
console.log("this is debug test")
function test () {console.log("hello world")
}
test()
});
复制代码

如果我们使用node --inspect来启动脚本,那整个代码直接运行到代码结尾,无法进行调试,但此时 Node 还进程没有结束,所以可以在 http://127.0.0.1:9229/json/list 查询 devtoolsFrontendUrl ,复制此 Url 到 Chrome 上进行调试。

看到使用 Chrome DevTools 的调试方法还是比较复杂的,一些 IDE 都支持直接断点调试,推荐WebStorm、VScode。

二、全局变量

在 Node 中常用的全局方法有 CommonJS、Buffer、process、console、timer 等,这些方法不需要 require引入 API 就可以直接使用。

如果希望有属性或方法可以*“全局使用”*,那就将它挂载在 Node 的global对象上:

global.gNum = 300
console.log(gNum); // 300
复制代码

在 Node 中所有模块都可以使用这些全局变量,以下就介绍 Node 中的全局变量

2.1 CommonJS 模块

Node CommonJS 模块规范根据实现了moduleexportsrequire模块机制。Node 对每个文件都被进行了模块封装,每个模块有自己的作用域,如在 debug 时看到的:

(function (exports, require, module, __filename, __dirname) { // some code
});
复制代码

模块机制中的 __dirname__filenameexportsmodulerequire()这些变量虽然看起来是全局的,但其实它们仅存在于模块范围。需要注意的几点是:

  • 模块内部module变量代表模块本身
  • 模块提供require()方法引入外部模块到当前的上下文中
  • module.exports属性代表模块对外接口,默认的快捷方式exports

简单的使用方式如下:

/* common_exports.js */
exports.num = 100
exports.obj = {a : 200
}
exports = {count : 300
}/* common_require.js */
const mod = require('./common_exports')
console.log(mod) // { num: 100, obj: { a: 200 } }
console.log(mod.count)  // undefined
复制代码

注意到上例中的mod.countundefined,这是因为exports只是module.exports的引用,可以给exports添加属性,但不能修改exports的指向。

更深入的了解模块机制可以看 【Node】前后端模块规范与模块加载原理

2.2 process 进程对象

process 包含了进程相关的属性和方法,Node 的 process 文档 中的内容特别多,列举几个常用方法。

Node 进程启动时传递的参数都在 process.arg数组中:

// process.js
const {argv , execPath} = processargv.forEach((val, index) => {console.log(`${index}: ${val}`)
})
console.log(execPath)
复制代码

可以在执行 process.js 时传递其他参数,这些参数都会保存在argv中:

$ node apiTest/process.js one=1 --inspect --version
0: /usr/local/bin/node
1: /Users/mobike/Documents/webProjects/testNode/apiTest/process.js
2: one=1
3: --inspect
4: --version
/usr/local/bin/node
复制代码

process.argv第一个参数就是 process.execPath ,即调用执行程序 Node 的路径,第二个参数时被执行的 JS 文件路径,剩下的就是自定义参数。


process.env是包含运行环境各种参数的对象,可以直接输出env查看所有参数信息,也可以输出某个属性:

const env = process.env
console.log(env.PATH) // /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/Documents/webProjects/testNode/node_modules/.bin
console.log(env.SHELL) // /bin/zsh
复制代码

在 webpack 打包过程中常用process.env.NODE_ENV判断生产环境或开发环境,process.env是没有NODE_ENV这个属性的,你可以在系统环境变量中配置,也可以在项目程序直接设置process.env.NODE_ENV=‘dev’


process.cwd()方法返回 Node.js 进程的当前工作目录,和 Linus 命令$ pwd功能一样:

// process.js
console.log(process.cwd()) // /Users/Documents/webProjects/testNode
复制代码
$ node process.js
/Users/WebstormProjects/testNode
$ pwd
/Users/WebstormProjects/testNode复制代码

2.3 Timers 异步

Node 中的计时器方法与 Web 浏览器中的JS 计时器类似,但内部实现是基于 Node 的 Event Loop。Node 中的计时器有setImmediate()setTimeout()setInterval()

在 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
nextTick
nextTick inner
setTimeout 0
setImmediate
setTimeout 100
复制代码

process.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'))   // 4
console.log(Buffer.byteLength('测试'))    // 6
console.log(Buffer.isBuffer('test'))     // false
console.log(Buffer.isBuffer(buf1))       // true
console.log(Buffer.concat([buf1, buf2])) // <Buffer 03 04 05 74 65 73 74>复制代码

除此之外,Buffer 实例也有常用的属性和方法,类似 JS 中的 String,有lengthtoString('base64')equals()indexOf()等。

以上就是 Node 全局变量的概述,其他的 API 或内置模块都需要· require('xxx')引入使用,我们可以在 nodejs.cn 中查看关于 Global API 更详细的介绍。

三、基础 API

3.1 path 路径相关

path 是处理和路径相关问题的内置 API,可以直接require('path')使用。以下示例常用的 path 方法。

对路径的处理常用path.normalize()规范路径、path.join()拼接路径,以及使用path.resolve()将相对路径解析为绝对路径:

const path = require('path')
console.log(path.normalize('//asd\/das'), // /asd/daspath.join('user', 'local'),   // user/localpath.resolve('./'))           // /Users/Documents/webProjects/testNode/apiTest
复制代码

解析某个路径,可以用path.basename()得到文件名称,path.extname()得到后缀扩展名,path.dirname()得到目录名:

const path = require('path')
const filePath = 'webProjects/testNode/apiTest/path.js'
console.log(path.basename(filePath), // path.js path.extname(filePath)   // .js path.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 对路径的常用操作,需要注意的是,在获取路径时有几种方式,得到的路径是不同的:

  • __dirname__filename:总是返回文件绝对路径;
  • process.cwd()$ pwd :返回执行 Node 命令的文件夹;
  • path.resolve('./'):是相对 Node 启动文件夹,在require()./是相对于当前文件夹;

3.3 events 事件

大部分 Node API 都采用异步事件驱动,所有能触发事件对象都是 EventEmitter 类的实例,通过 EventEmitter.on()绑定事件,然后通过 EventEmitter.emit() 触发事件。

// apiTest/events.js
const Events = require('events')class MyEvents extends Events{
}
const event = new MyEvents()event.on('test-event',()=>{console.log('this is an event')
})event.emit('test-event')
setInterval(()=>{event.emit('test-event')
},500)
复制代码

执行以上代码会一直连续处罚 test-event 事件,当然还可以传递事件参数,并且可以传递多个参数。修改上诉代码如下:

event.on('test-event', (data, time) => {console.log(data,time)
})
event.emit('test-event', [1, 2, 3], new Date())
复制代码
$ node apiTest/events.js
[ 1, 2, 3 ] 2019-04-23T07:28:00.420Z
复制代码

同一个事件监听器可以绑定多个事件,触发时按照绑定顺序加入执行队列,并且可以使用EventEmitter.removeListener()删除监听器的事件:

function fn1 () {console.log('fn1')
}
function fn2 () {console.log('fn2')
}
event.on('multi-event',fn1)
event.on('multi-event',fn2)setInterval(()=>{event.emit('multi-event')
},500)
setTimeout(()=>{event.removeListener('multi-event', fn2)
}, 600)
复制代码
$ node apiTest/events.js
[ 1, 2, 3 ] 2019-04-23T07:39:11.624Z
fn1
fn2
fn1
fn1
...
复制代码

3.4 fs 文件系统

Node 文件模块通过require('fs)使用,所用方法都有同步和异步方法。

文件系统中的异步方法,第一个参数保留给异常,操作成功时参数值为nullundefined,最后一个参数就是回调函数。例如读取文件的fs.readFile()和写文件的fs.writeFile()示例如下:

const fs = require('fs')fs.readFile('./apiTest/fs.js', (err, data) => {if (err) throw errconsole.log('readFile done!!!')
})fs.writeFile('./apiTest/fs.txt', 'this is test file', {encoding: 'utf8'
}, (err) => {if (err) throw errconsole.log('writeFile done!!!')
})
复制代码

推荐 nodejs.cn 中的 Docs API 中文版查看更多 Node API 的使用。


加油呢少年~

【Node】常用基础 API 整理相关推荐

  1. linux常用基础命令整理

    linux常用基础命令整理 su - 用户名 ->切换到指定用户下 ls ------>查看当前目录下的目录及文件 clear ------>清理屏幕 cd 路径 -----> ...

  2. 在linux系统环境中 常用的关机命令,Linux常用基础命令整理:关机命令、查看目录下文件命令等...

    整理了一些Linux常用基础命令,欢迎指正. 首先记住四个热键,学会这四个键,收益一辈子. Tab按键---命令补齐功能 Ctrl+c按键---停掉正在运行的程序 Ctrl+d按键---相当于exit ...

  3. JAVA常用基础API(经典实例)

    API文档注释写法 实例: package apidoc; /*** 在类上面写文档注释,是用来说明当前类的设计目的.功能* @author ta* @version 1.0* @see java.l ...

  4. 音视频学习之ffmpeg常用基础命令整理

    基于windows环境安装好必要的ffmpeg后,对ffmpeg基础命令进行一些了解: 1:ffmpeg查看版本: ffmpeg -version 2:ffmpeg查询命令: 基本信息:ffmpeg ...

  5. Jedis常用API整理-详细

    Jedis常用API整理 redis是一种高级的key-value的存储系统 其中的key是字符串类型,尽可能满足如下几点: 其中value 支持五种数据类型: jedis语法总结 1. jedis中 ...

  6. python常用变量名_python基础知识整理

    Python Python开发 Python语言 python基础知识整理 序言:本文简单介绍python基础知识的一些重要知识点,用于总结复习,每个知识点的具体用法会在后面的博客中一一补充程序: 一 ...

  7. JavaScript一些常用 API整理汇总

    JavaScript一些常用 API整理汇总 Array new Set() 数组去重 const arr = [3,4,4,5,4,6,5,7]; console.log(new Set(arr)) ...

  8. python常用api_[原创]IDAPython常用API整理

    IDAPython常用API整理:通过一些脚本和<IDA Pro权威指南>,查阅官网的IDAPython API整理,不算很多,有待增添. idaapi.MinEA():获取载入程序的最小 ...

  9. java基础知识点整理一

    java基础知识点整理一 引言 '''突然发觉任何一门语言的基础知识部分,都比较杂一些.如果个人经过梳理之后,知识体系系统化,可以让基础更加牢靠一些.但是还是会有一些遗忘.所以,我想把一些比较重要但是 ...

最新文章

  1. 云起作者微博认证在哪_UZI的期待实现了!厂长改认证明示复出,将再现“猪狗大战”荣光...
  2. 基于Windows 2008 R2 Core的SQL Server 2008 R2 Cluster部署(Step by Step)
  3. [音乐欣赏]Craigie Hill
  4. JSON.stringify()方法
  5. 数值计算 插值与拟合
  6. Tomcat实现session的代码逻辑分析
  7. 白硕 | 基于区块链的众包社区激励机制
  8. python-Python 3中字符串可以被改变吗?
  9. 爆火的Java面试题-kafka源码解析与实战豆瓣
  10. mfc mysql delete_MFC中简单的数据库文件操作(添加,修改,查找,删除)
  11. php公众获取用户信息,PHP--通过公众号获取用户微信信息
  12. Base64码常见操作(url链接文件转base64编码、本地文件转base64编码等)
  13. Microsoft Office 2019 正式版 安装记录
  14. 华南理工大学 电力电子技术(王兆安) 期末复习笔记2 第三章第四章
  15. FS7022双节锂电池8.4V保护IC电路图
  16. 网络准入系统usersafe守护企业内网安全
  17. 首款国产8K 50P小型化广播级摄像机惊喜亮相冬季冰雪体育盛会
  18. mysql 免费么,mysql收费吗
  19. 浅谈量子纠缠,易经,能量,世界(一)
  20. 录音文件下载_录音转文字别烦恼,收下这份锦囊,几种方法任你选!

热门文章

  1. boost::lexical_cast模块将创建一个to_long_double方法,将 Boost.Variant 的值转换为long double
  2. boost::hana::less_equal用法的测试程序
  3. boost::hana::flip用法的测试程序
  4. boost::graph模块实现包含平均测地线示例
  5. boost::boost::directed_graph用法的测试程序
  6. 宏BOOST_TEST_TRAIT_TRUE的用法
  7. Boost:bind绑定和或||的测试程序
  8. C++kruskals算法生成最小协议树(附完整源码)
  9. np.insert()
  10. android 蓝牙打印格式,Android蓝牙打印格式排版