Nodejs 基础

最佳实践:

运行node添加环境变量:$ export VAR=dev && node tem.js
在脚本中可以通过process.env.VAR读取

__dirname, __filename, process.cwd()(node 命令时所在的文件夹), ./ 或者 ../,前三个都是绝对路径, 前两个不能在 repl 中运行,前两个使用 webpack 打包时默认会被替换
// 相对路径在require中是相对自己,在其它位置是相对node执行目录。

事件驱动、非阻塞I/O、高效、轻量
JS调用I/O -> v8解释执行 -> Node核心模块 libuv 封装成请求对象推入I/O线程池等待执行 -> JS发起异步调用结束,继续执行队列
I/O操作完成后储存结果到请求对象的 result 属性上发出通知 -> 事件循环(无限循环)时检测到 I/O 操作完成将其加入到观察者队列 -> JS执行

如果写同步函数要要使用 try...catch 来获取错误信息

Javascript 单线程,所以不适合处理CPU密集型的应用,如压缩,解压缩,加/解密等操作

CommonJS 规范 ./相对路径,nodejs支持类似foo/bar的写法自动查找,可添加NODE_PATH
require(还可以导入json) exports(导出的对象)
module(访问到当前模块的一些信息,如module.exports = function)

可以使用二进制模块

包有一个入口模块,入口模块的导出对象被作为包的导出对象
当入口模块文件名为 index.js,直接可以使用模块路径来导入,如果不是这个文件名也可以通过package.json来指定,其中还可以指定依赖,npm批量下载依赖包。

fs模块(异步需要回调函数,同步添加Sync):
fs.writeFile、fs.readFile、fs.stat、fs.chmod、fs.chown、fs.readdir、fs.mkdir、fs.open、fs.read、fs.write、fs.close

path.normalize\path.join\path.extname

Stream 基于事件机制工作,所有 Stream 的实例都继承于 NodeJS 提供的EventEmitter。rs.on('end', function), .pause(); .resume(),HTTP 请求和响应是一个数据流。
fs.createReadStream(src).pipe(fs.createWriteStream(dst));
Buffer,跟字符串有个很大的不同就是可以修改,slice 也是会作用于原 Buffer。.copy()

http模块创建的HTTP服务器在接收到完整的请求头后,就会调用回调函数。在回调函数中,除了可以使用request对象访问请求头数据外,还能把request、response对象当作一个只读数据流来访问请求体数据(如何把response当作流来发送,还不需要end方法?)。http.ServerRequest 并没有一个属性内容为请求体,原因是等待请求体传输可能是一件耗时的工作,譬如上传文件。而很多时候我们可能并不需要理会请求体的内容,恶意的 POST请求会大大消耗服务器的资源。所以 Node.js 默认是不会解析请求体的,当你需要的时候,需要监听req的data和end事件来获取请求体。req的socket是一个socket实例,默认buffer,而req的是默认utf-8编码。
多次response.write('hello');自动变成分块传输

创建HTTPS服务器时多一个证书参数,还可以用server.addContext添加多个证书用来根据请求域名动态使用不同证书

创建https请求时默认会拒绝连接自制证书的服务器,可以在options对象中添加rejectUnauthorized: false字段可以禁用对证书有效性的检查

使用 http 模块时 NodeJS 将请求头字段统一转换成了小写,当没有在响应头中写主体长度字段时NodeJS会自动添加 Transfer-Encoding

url.parse,url.format,url.resolve,querystring.parse

net 模块用于创建 Socket 链接,http 头以及主体都是直接写的(头和主体用空行分割,Transfer-Encoding: chunked 时主体也会空行分割)。获得的响应不是流数据了?直接通过data事件获得响应。

process是一个全局变量,可通过process.argv获得命令行参数。由于argv[0]固定等于NodeJS执行程序的绝对路径,argv[1]固定等于主模块的绝对路径,因此第一个命令行参数从argv[2]这个位置开始。
NodeJS程序的标准输入(stdin)、一个标准输出(stdout)、一个标准错误(stderr)分别对应process.stdin、process.stdout和process.stderr(子进程也有的)
非win系统的系统信号SIGINT(ctrl+c)和内核信号SIGTERM会使node进程退出,监听这两个信号就不会退出(只对SIGINT有效?
给 process 对象添加 uncaughtException 事件绑定能够避免发生异常时进程直接退出(完成任务后在退出)。在回调函数里调用当前运行 server 对象的 close 方法,停止接收新的连接。同时告知 master 进程该 worker 进程即将退出,可以 fork 新的 worker 了。

使用child_process模块可以创建和控制子进程
child_process模块用于新建子进程。子进程的运行结果储存在系统缓存之中(最大200KB),等到子进程运行结束以后,主进程再用回调函数读取子进程的运行结果。
spawn 是一个旨在运行系统命令的命令。fork 是一个特殊的 spawn 实例,它运行一个新的 V8 引擎实例
spawn 第一个参数是执行文件路径,第二个参数对应命令行参数(exeFile一样,区别是回调且不是子进程),close 事件
进程间进行通信,可以用.kill方法传递信号,NodeJS父子可以通过 IPC(进程间通讯)双向传递数据(有点像浏览器端的worker)
守护子进程。进程异常退出的退出码不等于0

cluster 模块是对 child_process 模块的进一步封装,专用于解决单进程 NodeJS Web 服务器无法充分利用多核CPU 的问题。使用该模块可以简化多进程服务器程序的开发,让每个核上运行一个工作进程,并统一通过主进程监听端口和分发请求

NodeJS提供了domain模块,可以简化异步代码的异常处理。一个域就是一个JS运行环境,在一个运行环境中,domain将捕获域中的异常
.create方法创建了一个子域对象,并通过.run方法进入需要在子域中运行的代码的入口点,子域中的异步函数回调函数不再需要捕获异常,全部抛给子域,触发子域error事件

使用 nvm 管理node版本

nodejs 打开了文件和脚本未执行完就不会自动退出,比如监听端口,监听stdin,setInterval