基础知识,进程和线程

1.概念

node是基于v8的,也就注定和浏览器类似,单线程的。但是node的作用大多作为服务器,单线程的情况下一旦出现异常,整个程序就挂掉了,所以为了保证程序的稳定性,多进程的使用也就很有必要了。

node中的进程有process和child_process

2.process

process是全局对象的一个属性,作用一般用来获取node进程相关的信息,而不是用来新建进程。

2.1 process的属性

2.1.1 命令行参数

console.log('argv: ', process.argv)
console.log('argv[0]:', process.argv[0])
console.log('argv0:', process.argv0)
console.log('execPath:', process.execPath)

  process git:(master)  node index.js a=1 b=2
argv:  [ '/Users/yangming/.nvm/versions/node/v8.11.4/bin/node',
  '/Users/yangming/Documents/github/nodejs-learn/example/process/index.js',
  'a=1',
  'b=2' ]
argv[0]: /Users/yangming/.nvm/versions/node/v8.11.4/bin/node
argv0: node
execPath: /Users/yangming/.nvm/versions/node/v8.11.4/bin/node
 bash -c 'exec -a customArgv0 node'
 > process.argv0
 'customArgv0'

返回node启动时内部定义的参数选项,参数选项的具体可以node -h查看

这些选项在process.argv属性返回的数组中不会出现,并且这些选项中不会包括Node.js的可执行脚本名称或者任何在脚本名称后面出现的选项。 这些选项在创建子进程时是有用的,因为他们包含了与父进程一样的执行环境信息。

2.1.2 标准的输入输出

它的返回连接到stdin (fd 0)的流,它是一个Duplex流,除非 fd 0指向一个文件,在这种情况下它是一个Readable流。

关于fd表示文件描述符,当我们fs.open一个文件时,就会返回fd。详情请戳文件描述符

process.stdin.setEncoding('utf8')

// 网上全是这样的demo,我们在stream那章学习过,要避免使用`readable`事件和`readable.read()`方法
// process.stdin.on('readable', () => {
//   const chunk = process.stdin.read()
//   if (chunk !== null) {
//     process.stdout.write(`data: ${chunk}`)
//   }
// })
process.stdin.on('data', chunk => {
  process.stdout.write(`data: ${chunk}`)
})

process.stdin.on('end', () => {
  process.stdout.write('end')
})
fs.createReadStream('index.js').pipe(process.stdout)

process.stdout and process.stderr 与 Node.js 中其他 streams 在重要的方面有不同:

2.1.3 环境变量

就和普通的对象一样

process.env

{
  PWD: '/Users/yangming/Documents/github/nodejs-learn/example/process',
  OLDPWD: '/Users/yangming/Documents/github/nodejs-learn/example',
  rvm_prefix: '/Users/yangming',
  rvm_path: '/Users/yangming/.rvm',
  rvm_bin_path: '/Users/yangming/.rvm/bin',
  _system_type: 'Darwin',
  _system_name: 'OSX',
  _system_version: '10.13',
  _system_arch: 'x86_64',
}

新增process.env.test,删除delete process.env.test


2.2 process的方法

2.2.1 process.kill(pid, signal)

process.kill()方法将signal发送给pid标识的进程,signal默认为'SIGTERM'

signal event如下

SIGHUP 默认的绑定行为是结束Node.js,但是一旦给它绑定了新的监听器,默认行为会被移除。
SIGINT `<Ctrl>+C`触发
SIGTERM 在非windows平台绑定了默认的监听器,这样进程以代码128 + signal number结束之前,可以重置终端模式。  如果这两个事件任意一个绑定了新的监听器,原有默认的行为会被移除(Node.js不会结束)。

详细请戳信号事件

2.2.2 process.exit([code])

以结束状态码code指示Node.js同步终止进程。 如果code未提供,此exit方法要么使用’success’ 状态码 0,要么使用process.exitCode属性值,前提是此属性已被设置。 Node.js在所有’exit’事件监听器都被调用了以后,才会终止进程。

注意点

应该避免显示的调用process.exit(),因为会丢弃异步操作,进程一般会自然结束,我们只需要设置process.exitCode来告诉系统以哪种code结束进程即可。

进程的退出码

2.2.3 process.chdir(directory)

变更Node.js进程的当前工作目录

当前工作路径即process.env.PWDprocess.cwd()得到

console.log(`Starting directory: ${process.cwd()}`)
try {
  process.chdir('../stream')
  console.log(`New directory: ${process.cwd()}`)
} catch (err) {
  console.error(`chdir: ${err}`)
}

2.2.4 process.emitWarning(warning[, type[, code]][, ctor])

用于发出定制的或应用特定的进程警告,参数:

warning可以理解为是一个Error对象,包含name message code stack


2.3 process的事件

2.3.1 ‘exit’

‘exit’ 事件监听器的回调函数只允许同步操作,因为异步操作会被丢弃,因为非本次事件循环的事件都不在执行

process.on('exit', code => {
  setTimeout(() => {
    console.log('该函数不会被执行')
  }, 0)
})

2.3.2 ‘warning’

任何时候Node.js发出进程告警,都会触发’warning’事件

process.on('warning', (warning) => {
  console.warn(warning.name);    // 打印告警名称
  console.warn(warning.message); // 打印告警信息
  console.warn(warning.stack);   // 打印堆栈信息
});

可以配合process.emitWarning()使用


2.4 IPC相关

具体请戳创建进程child_process