File System

fs.access

判断对一个文件是否有权限, 参数为 filenamemode :

  • fs.constants.F_OK:在当前进程存在与否
  • fs.constants.R_OK:读取
  • fs.constants.W_OK:写入
  • fs.constants.X_OK:执行
    1. try {
    2. fs.accessSync('etc/passwd', fs.constants.R_OK | fs.constants.W_OK);
    3. console.log('can read/write');
    4. } catch (err) {
    5. console.error('no access!');
    6. }

    HTTP

    http.Agent

    Agent 用来为 http 客户端管理连接的持久性和复用性。对于同一个 host 和 port,Agent 维护了一个进行中的请求的队列,其中的每个请求都会复用同一个 socket connection 。当队列为空时,这个 socket connection 会被销毁或者放入到 socket 池中,以供后续对同一个 host 和 port 的请求使用。销毁或者放入池中取决于 keepAlive 选项。

对于放入池中的链接,默认启用了 TCP 的 Keep Alive,但是如果服务器关掉了空闲的连接,池中的连接会被移除,此后对于同一个 host 和 post 的 http 请求,会重新建立新的连接。 服务器也可能拒绝多个请求使用同一个 socket connection,此时每个请求就必须建立新的连接,并且不能将连接放入池中。

当服务器或者客户端关闭了连接之后,该连接会被移除连接池。任何已经不被使用的 socket 将被销毁,以避免在没有请求时保持 Node.js 进程运行。

对于不使用的 Agent 实例,最好是 destroy 它,不使用的 socket 会消耗操作系统的资源。

如果一个 socket 发出了 closeagentRemove 事件,它将被移出 Agent .如果想长时间保持一个 request 开启,但不想把它放在 Agent 里面,可以使用如下代码:

  1. http.get(options, (res) => {
  2. // Do stuff
  3. }).on('socket', (socket) => {
  4. socket.emit('agentRemove');
  5. });

Buffer

文档

感觉把API挨个写出来没啥意义,还浪费时间。改为看文档吧,多看几遍并经常复习总会烂记于心。

Nodejs中 Buffer 用来以字节序列的方式展现二进制数据。Buffer 是 Uint8Array 的子集,存放的都是0~255的整数,但是 Buffer 所占的内存空间已经分配不可改变。

在进行与字符串的相互转化时可以指定编码格式:

  1. const buf = Buffer.from([ '3', 'hello' ]);
  2. buf.toSting('utf8');

支持的编码格式如下:

  • utf8
  • utf16le, 与 ucs2 相同
  • latin1, 与 binary 相同
  • base64
  • ascii
  • hex

常用API介绍

类方法

Buffer.from

  • Buffer.from(array)
  • Buffer.from(buffer)
  • Buffer.from(string, encoding), 默认 utf8
  • Buffer.from(arrayBuffer, offset, length)
  • Buffer.from(Object, offsetOrEncoding, length)
    1. const buffer = Buffer.from('888338', 'utf8');

    Buffer.alloc(size, fill, encoding)

    创建 Buffer 实例,分配内存,并初始化其中的数据

Buffer.allocUnsafe(size)

创建实例,分配内存,但不初始化,有可能含有旧的数据

Buffer.allocUnsageSlow(size)

一般分配内存时,如果大小小于4KB,则是从事先分配好的内存池中分配,这样可以避免重复的垃圾回收,就是直接分配内存,而不是从事先分配好内存池中分配。

Nodejs 会事先分配一块内存池供使用,需要的内存都从这个地方分配,可以避免垃圾回收因为过多的内存块而过度使用。这样可以消除了追踪和清理工作,提高了性能。

Buffer.byteLength(string, encoding)

查询数据的字节长度,可以传入 string、ArrayBuffer、ArrayBuffer、Array、Buffer等

Buffer.isEncoding(encoding)

是否某个编码是否支持。如果是支持的,返回 true

Stream

https://github.com/jabez128/stream-handbook

child_process

spawn

spawn 衍生一个新的进程,用来执行传入的命令。可以通过返回的子进程的 stdout 来监听命令执行的输出。

  1. import { spawn } from "child_process"
  2. /**
  3. * https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
  4. * 第二个参数可以是命令的参数,也可以没有
  5. * 第三个参数传入 options
  6. * - cwd
  7. * - env
  8. * - stdio
  9. * - detached: 指定子进程独立于父进程运行
  10. * - shell: 如果为 true,会在一个 shell 中运行命令,也可以通过字符串指定一个不同的 shell,
  11. */
  12. const ls = spawn('ls', [ '-lh', '.' ], {
  13. cwd: process.cwd(),
  14. env: process.env,
  15. argv0: '-lh',
  16. detached: true,
  17. uid: undefined,
  18. gid: undefined,
  19. serialization: 'advanced',
  20. })
  21. ls.stdout.on('data', data => {
  22. console.log(`stdout: ${data}`)
  23. })
  24. ls.stderr.on('data', data => {
  25. console.log(`stderr: ${data}`)
  26. })
  27. /**
  28. * 一旦子进程成功衍生,不论内部执行是否出错,都会触发本事件,否则触发 `error`
  29. * 总是最先触发,早于其它事件和 stdout 和 stderr 事件
  30. */
  31. ls.on('spawn', () => {
  32. console.log('spawn');
  33. })
  34. /**
  35. * 子进程通过 process.send() 发送消息时会触发此事件,
  36. * message: 对象
  37. * sendHandler: A net.Socket or net.Server object, or undefined.
  38. */
  39. ls.on('message', (message, sendHandler) => {
  40. console.log(message, sendHandler);
  41. })
  42. /**
  43. * 当进程结束时抛出,此时 stdio 可能还没有断开
  44. * 如果是通过新号关闭的,则第二个参数会是字符串,否则是 null
  45. */
  46. ls.on('exit', (code, signal) => {
  47. console.log('exit: ', code)
  48. })
  49. /**
  50. * 当进程结束且 stdio 都关闭时抛出,总是在 exit 或者 error 事件之后
  51. * signal 为结束时的信号
  52. */
  53. ls.on('close', code => {
  54. console.log('close:', code)
  55. })
  56. /**
  57. * 调用 subprocess.disconnect() 或者在子进程内调用 process.disconnect()
  58. */
  59. ls.on('disconnect', () => {
  60. console.log('disconnect');
  61. })
  62. /**
  63. * error 事件的触发:
  64. * 1. spawn 失败
  65. * 2. kill 失败
  66. * 3. send message 失败
  67. *
  68. * error 事件之后,exit 事件可能会或不会触发,需要防止同样的事件处理器调用两次
  69. */
  70. ls.on('error', () => {
  71. console.log('error')
  72. })

exec

  1. child_process.exec(command[, options][, callback])

衍生一个 shell 然后执行传入的命令。exec 缓存命令执行的输出,然后传入到回调中,所以只适合数据量比较小的命令。

execFile

  1. child_process.execFile(file[, args][, options][, callback])
  2. const { execFile } = require('child_process');
  3. const child = execFile('node', ['--version'], (error, stdout, stderr) => {
  4. if (error) {
  5. throw error;
  6. }
  7. console.log(stdout);
  8. });

execFile用来执行一个可执行文件或者命令,可以传入参数。
与 exec 类似,但是 execFile不会默认衍生一个shell,而是直接衍生一个进程,所以会比 exec更加高效。

fork

  1. child_process.fork(modulePath[, args][, options])
  • child_process fork 属于 spawn 的一种特殊用法,会默认衍生一个 Nodejs 进程并执行给定的模块或文件。
  • 子进程内置了 IPC 通道,可以和父进程进行通信
  • 子进程独立于父进程,会分配额外的资源,所以不建议衍生太多进程
  • execPath 默认与父进程的相同,可以进行指定