简介
Node.js 就是运行在服务端的 JavaScript,是一个平台,提供I/O接口,基于Google的V8引擎
创建第一个应用
脚本模式
|
|
并通过 node命令来执行,输出Hello World!
|
|
交货模式
打开终端,键入node进入命令交互模式,可以输入一条代码语句后立即执行并显示结果
|
|
NPM 使用介绍
NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用
- 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用
使用 npm 命令安装模块
使用 npm 命令安装常用的 Node.js web框架模块 express
|
|
安装好之后,express 包就放在了工程目录下的 node_modules 目录中
因此在代码中只需要通过 require(‘express’) 的方式就好,无需指定第三方包路径
|
|
全局安装与本地安装
npm 的包安装分为本地安装、全局安装
|
|
本地安装
- 将安装包放在 ./node_modules 下,如果没有 node_modules 目录
- 可以通过 require() 来引入本地安装的包
全局安装
- 将安装包放在 /usr/local 下或者你 node 的安装目录。
- 可以直接在命令行里使用
使用 package.json
package.json 位于模块的目录下,用于定义包的属性,属性说明
- name - 包名
- version - 包的版本号
- description - 包的描述
- homepage - 包的官网 url
- author - 包的作者姓名
- contributors - 包的其他贡献者姓名
- dependencies - 依赖包列表。如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下
- repository - 包代码存放的地方的类型,可以是 git 或 svn,git 可在 Github 上
- main - main 字段指定了程序的主入口文件,require(‘moduleName’) 就会加载这个文件。这个字段的默认值是模块根目录下面的 index.js
- keywords - 关键字
卸载模块
使用以下命令来卸载 Node.js 模块
|
|
更新模块
使用以下命令更新模块
|
|
搜索模块
使用以下来搜索模块
|
|
创建模块
创建模块,package.json 文件是必不可少的
|
|
使用以下命令在 npm 资源库中注册用户(使用邮箱注册)
|
|
用以下命令来发布模块
|
|
NPM 常用命令
NPM提供了很多命令,例如install和publish,使用npm help可查看所有命令
- 使用npm help
可查看某条命令的详细帮助,例如npm help install - 在package.json所在目录下使用npm install . -g可先在本地安装当前命令行程序,可用于发布前的本地测试
- 使用npm update
可以把当前目录下node_modules子目录里边的对应模块更新至最新版本 - 使用npm update
-g可以把全局安装的对应命令行程序更新至最新版 - 使用npm cache clear可以清空NPM本地缓存,用于对付使用相同版本号发布新版本代码的人
- 使用npm unpublish
@ 可以撤销发布自己发布过的某个版本代码
使用淘宝 NPM 镜像
|
|
REPL(交互式解释器)
Node 自带了交互式解释器,可以执行以下任务
- 读取 - 读取用户输入,解析输入了Javascript 数据结构并存储在内存中。
- 执行 - 执行输入的数据结构
- 打印 - 输出结果
- 循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出
输入以下命令来启动 Node 的终端
|
|
简单的表达式运算
|
|
使用变量
将数据存储在变量中,并在你需要的时候使用它
|
|
多行表达式
Node REPL 支持输入多行表达式,这就有点类似 JavaScript
|
|
下划线(_)变量
使用下划线(_)获取上一个表达式的运算结果
|
|
REPL 命令
- ctrl + c - 退出当前终端
- ctrl + c 按下两次 - 退出 Node REPL
- ctrl + d - 退出 Node REPL
- 向上/向下 键 - 查看输入的历史命令
- tab 键 - 列出当前命令
- .help - 列出使用命令
- .break - 退出多行表达式
- .clear - 退出多行表达式
- .save filename - 保存当前的 Node REPL 会话到指定文件
- .load filename - 载入当前 Node REPL 会话的文件内容
停止 REPL
两次 ctrl + c 键就能退出 REPL
|
|
回调函数
Node.js 异步编程的直接体现就是回调
回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数
一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。执行代码时就没有阻塞或等待文件 I/O 操作
阻塞代码实例
|
|
非阻塞代码实例
|
|
事件循环
Node.js 是单进程单线程应用程序,V8 引擎提供的异步执行回调接口
Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现
Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数
事件驱动程序
Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求
当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户
在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数

Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件
|
|
绑定及触发事件处理程序
|
|
实例
|
|
应用程序工作机制
在 Node 应用程序中,回调函数接收错误对象作为第一个参数,执行异步操作的函数将回调函数作为最后一个参数
|
|
EventEmitter
Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列
EventEmitter 类
events 模块只提供了一个对象: events.EventEmitter
EventEmitter 的核心就是事件触发与事件监听器功能的封装
|
|
EventEmitter 对象如果在实例化时发生错误,会触发 error 事件
当添加新的监听器时,newListener 事件会触发,当监听器被移除时,removeListener 事件被触发
|
|
EventEmitter 的每个事件由一个事件名和若干个参数组成,事件名是一个字符串,通常表达一定的语义
对于每个事件,EventEmitter 支持 若干个事件监听器
当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递
|
|
EventEmitter 提供了多个属性,如 on 和 emit。on 函数用于绑定事件函数,emit 属性用于触发一个事件
方法
addListener(event, listener):为指定事件添加一个监听器到监听器数组的尾部
on(event, listener):为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数
|
|
- once(event, listener):为指定事件注册一个单次监听器,即 监听器最多只会触发一次,触发后立刻解除该监听器
|
|
- removeListener(event, listener):移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器
|
|
removeAllListeners([event]):移除所有事件的所有监听器, 如果指定事件,则移除指定事件的所有监听器
setMaxListeners(n):setMaxListeners 函数用于提高监听器的默认限制的数量
listeners(event):返回指定事件的监听器数组
emit(event, [arg1], [arg2], […]):按参数的顺序执行每个监听器,如果事件有注册监听返回 true,否则返回 false
类方法
- listenerCount(emitter, event):返回指定事件的监听器数量
事件
newListener(emitter, event):该事件在添加新监听器时被触发
removeListener(emitter, event):从指定监听器数组中删除一个监听器
实例
通过 connection(连接)事件演示了 EventEmitter 类的应用
|
|
error 事件
EventEmitter 定义了一个特殊的事件 error,它包含了错误的语义,我们在遇到 异常的时候通常会触发 error 事件
一般要为会触发 error 事件的对象设置监听器,避免遇到错误后整个程序崩溃
|
|
继承 EventEmitter
大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它
包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类
Buffer(缓冲区)
JavaScript 语言自身只有字符串数据类型,没有二进制数据类型
处理像TCP流或文件流时,必须使用到二进制数据
Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区
Buffer 与字符编码
Buffer 实例一般用于表示编码字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六进制编码的数据
|
|
Node.js 目前支持的字符编码包括
- ascii - 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的
- utf8 - 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8
- utf16le - 2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)
- ucs2 - utf16le 的别名
- base64 - Base64 编码
- latin1 - 一种把 Buffer 编码成一字节编码的字符串的方式
- binary - latin1 的别名
- hex - 将每个字节编码为两个十六进制字
创建 Buffer 类
Buffer 提供了以下 API 来创建 Buffer 类
- Buffer.alloc(size[, fill[, encoding]]): 返回一个指定大小的 Buffer 实例,如果没有设置 fill,则默认填满 0
- Buffer.allocUnsafe(size): 返回一个指定大小的 Buffer 实例,但是它不会被初始化,所以它可能包含敏感的数据
- Buffer.allocUnsafeSlow(size)
- Buffer.from(array): 返回一个被 array 的值初始化的新的 Buffer 实例(传入的 array 的元素只能是数字,不然就会自动被 0 覆盖)
- Buffer.from(arrayBuffer[, byteOffset[, length]]): 返回一个新建的与给定的 ArrayBuffer 共享同一内存的 Buffer
- Buffer.from(buffer): 复制传入的 Buffer 实例的数据,并返回一个新的 Buffer 实例
- Buffer.from(string[, encoding]): 返回一个被 string 的值初始化的新的 Buffer 实例
|
|
写入缓冲区
buf.write(string[, offset[, length]][, encoding]),返回值:实际写入的大小。如果 buffer 空间不足, 则只会写入部分字符串
- canshu - 写入缓冲区的字符串
- offset - 缓冲区开始写入的索引值,默认为 0
- length - 写入的字节数,默认为 buffer.length
- encoding - 使用的编码。默认为 ‘utf8’
|
|
从缓冲区读取数据
buf.toString([encoding[, start[, end]]]),返回值:解码缓冲区数据并使用指定的编码返回字符串
- encoding - 使用的编码。默认为 ‘utf8’
- start - 指定开始读取的索引位置,默认为 0
- end - 结束位置,默认为缓冲区的末尾
|
|
将 Buffer 转换为 JSON 对象
buf.toJSON(),返回值:返回 JSON 对象
|
|
缓冲区合并
Buffer.concat(list[, totalLength]),返回一个多个成员合并的新 Buffer 对象
- list - 用于合并的 Buffer 对象数组列表
- totalLength - 指定合并后Buffer对象的总长度
|
|
缓冲区比较
buf.compare(otherBuffer),返回值:返回一个数字,表示 buf 在 otherBuffer 之前,之后或相同
- 与 buf 对象比较的另外一个 Buffer 对象
|
|
拷贝缓冲区
buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]]),没有返回值
- targetBuffer - 要拷贝的 Buffer 对象
- targetStart - 数字, 可选, 默认: 0
- sourceStart - 数字, 可选, 默认: 0
- sourceEnd - 数字, 可选, 默认: buffer.length
|
|
缓冲区裁剪
buf.slice([start[, end]]),返回值:返回一个新的缓冲区,它和旧缓冲区指向同一块内存,但是从索引 start 到 end 的位置剪切
- start - 数字, 可选, 默认: 0
- end - 数字, 可选, 默认: buffer.length
|
|
缓冲区长度
buf.length,返回值:返回 Buffer 对象所占据的内存长度
|
|
Stream(流)
Stream 是一个抽象接口,Node 中有很多对象实现了这个接口
Node.js,Stream 有四种流类型
- Readable - 可读操作
- Writable - 可写操作
- Duplex - 可读可写操作
- Transform - 操作被写入数据,然后读出结果
所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有
- data - 当有数据可读时触发
- end - 没有更多的数据可读时触发
- error - 在接收和写入过程中发生错误时触发
- finish - 所有数据已被写入到底层系统时触发
从流中读取数据
|
|
写入流
|
|
管道流
管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传递到另外一个流中
|
|
链式流
链式是通过连接输出流到另外一个流并创建多个流操作链的机制。链式流一般用于管道操作
用管道和链式来压缩和解压文件
|
|
解压该文件,创建 decompress.js 文件
|
|
模块系统
为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统
Node.js 提供了 exports 和 require 两个对象
- exports 是模块公开的接口
- require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象
创建模块
hello.js 通过 exports 对象把 world 作为模块的访问接口
main.js 中通过 require(‘./hello’) 加载这个模块
直接访 问 hello.js 中 exports 对象的成员函数
创建一个 main.js 文件
|
|
创建 hello.js 文件
|
|
把一个对象封装到模块中
|
|
获得这个对象
|
|
服务端的模块加载
Node.js 的 require 方法中的文件查找策略:4 类模块(原生模块和3种文件模块)
从文件模块缓存中加载:尽管原生模块与文件模块的优先级不同,但是都会优先从文件模块的缓存中加载已经存在的模块
从原生模块加载:原生模块的优先级仅次于文件模块缓存的优先级。require 方法在解析文件名之后,优先检查模块是否在原生模块列表中
从文件加载:当文件模块缓存中不存在,而且不是原生模块的时候,Node.js会解析require方法传入的参数,并从文件系统中加载实际的文件
require方法接受以下几种参数的传递
- http、fs、path等,原生模块
- ./mod或../mod,相对路径的文件模块
- /pathtomodule/mod,绝对路径的文件模块
- mod,非原生模块的文件模块
函数
Node.js中函数的使用与Javascript类似
|
|
匿名函数
没有名字的函数叫做匿名函数
|
|
HTTP服务器工作机制
我们向 createServer 函数传递了一个匿名函数
|
|
用这样的代码也可以达到同样的目的
|
|
路由
为路由提供请求的 URL 和其他需要的 GET 及 POST 参数,随后路由需要根据这些数据来执行相应的代码
所有数据都会包含在 request 对象中,该对象作为 onRequest() 回调函数的第一个参数传递
解析这些数据,需要Node.JS 模块,它们分别是 url 和 querystring 模块
|
|
onRequest() 函数加上一些逻辑,用来找出浏览器请求的 URL 路径
|
|
编写路由,新建router.js
|
|
路由和服务器整合
|
|
全局对象
Node.js 中的全局对象是 global,所有全局变量都是 global 对象的属性
__filename
当前正在执行的脚本的文件名,输出文件所在位置的绝对路径
|
|
__dirname
当前执行脚本所在的目录
|
|
process
当前Node.js 进程状态的对象,提供了一个与操作系统的简单接口
常用的方法
- exit: 当进程准备退出时触发
- beforeExit: 当 node 清空事件循环,并且没有其他安排时触发这个事件
- uncaughtException: 当一个异常冒泡回到事件循环,触发这个事件
- Signal事件: 当进程接收到信号时就触发
|
|
退出状态码
- 1-Uncaught Fatal Exception:有未捕获异常,并且没有被域或 uncaughtException 处理函数处理
- 2-Unused:保留
- 3-Internal JavaScript Parse Error:JavaScript的源码启动 Node 进程时引起解析错误
- 4-Internal JavaScript Evaluation Failure:JavaScript 的源码启动 Node 进程,评估时返回函数失败
- 5-Fatal Error:V8 里致命的不可恢复的错误。通常会打印到 stderr ,内容为: FATAL ERROR
- 6-Non-function Internal Exception Handler:未捕获异常,内部异常处理函数不知为何设置为on-function,并且不能被调用
- 7-Internal Exception Handler Run-Time Failure:未捕获的异常, 并且异常处理函数处理时自己抛出了异常
- 8-Unused:保留
- 9-Invalid Argument:可能是给了未知的参数,或者给的参数没有值
- 10-Internal JavaScript Run-Time Failure:JavaScript的源码启动 Node 进程时抛出错误
- 12-Invalid Debug Argument:设置了参数–debug 和/或 –debug-brk,但是选择了错误端口
- 128-Signal Exits:如果 Node 接收到致命信号,比如SIGKILL 或 SIGHUP,那么退出代码就是128 加信号代码
Process 属性
Process 提供了很多有用的属性,便于我们更好的控制系统的交互(查文档)
|
|
常用工具
util 是一个Node.js 核心模块,提供常用函数的集合
util.inherits
util.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数
|
|
util.inspect
util.inspect(object,[showHidden],[depth],[colors])是一个将任意对象转换 为字符串的方法,通常用于调试和错误输出
至少接受一个参数 object,即要转换的对象
showHidden 是一个可选参数,如果值为 true,将会输出更多隐藏信息
depth 表示最大递归的层数,如果对象很复杂,你可以指定层数以控制输出信息的多少,默认2层
color 值为 true,输出格式将会以ANSI 颜色编码
|
|
util.isArray(object)
如果给定的参数 “object” 是一个数组返回true,否则返回false
|
|
util.isRegExp(object)
如果给定的参数 “object” 是一个正则表达式返回true,否则返回false
|
|
util.isDate(object)
如果给定的参数 “object” 是一个日期返回true,否则返回false
|
|
util.isError(object)
如果给定的参数 “object” 是一个错误对象返回true,否则返回false
|
|
文件系统
Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API
Node 导入文件系统模块(fs)
|
|
异步和同步
Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本
读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()
|
|
打开文件
fs.open(path, flags[, mode], callback)
- path - 文件的路径
- flags - 文件打开的行为。具体值详见下文
- mode - 设置文件模式(权限),文件创建默认权限为 0666(可读,可写)
- callback - 回调函数,带有两个参数如:callback(err, fd)
|
|
获取文件信息
fs.stat(path, callback)
- path - 文件路径
- callback - 回调函数,带有两个参数如:(err, stats), stats 是 fs.Stats 对象
|
|
写入文件
fs.writeFile(file, data[, options], callback)
- file - 文件名或文件描述符
- data - 要写入文件的数据,可以是 String(字符串) 或 Buffer(流) 对象
- options - 该参数是一个对象,包含 {encoding, mode, flag}。默认编码为 utf8,模式为 0666 , flag 为 ‘w’
- callback - 回调函数,回调函数只包含错误信息参数(err),在写入失败时返回
|
|
读取文件
fs.read(fd, buffer, offset, length, position, callback)
- fd - 通过 fs.open() 方法返回的文件描述符
- buffer - 数据写入的缓冲区
- offset - 缓冲区写入的写入偏移量
- length - 要从文件中读取的字节数
- position - 文件读取的起始位置,如果 position 的值为 null,则会从当前文件指针的位置读取
- callback - 回调函数,有三个参数err, bytesRead, buffer,err 为错误信息, bytesRead 表示读取的字节数,buffer 为缓冲区对象
|
|
关闭文件
fs.close(fd, callback)
- fd - 通过 fs.open() 方法返回的文件描述符
- callback - 回调函数,没有参数
|
|
截取文件
fs.ftruncate(fd, len, callback)
- fd - 通过 fs.open() 方法返回的文件描述符
- len - 文件内容截取的长度
- callback - 回调函数,没有参数
|
|
删除文件
fs.unlink(path, callback)
- path - 文件路径
- callback - 回调函数,没有参数
|
|
创建目录
fs.mkdir(path[, mode], callback)
- path - 文件路径
- mode - 设置目录权限,默认为 0777
- callback - 回调函数,没有参数
|
|
读取目录
fs.readdir(path, callback)
- path - 文件路径
- callback - 回调函数,回调函数带有两个参数err, files,err 为错误信息,files 为 目录下的文件数组列表
|
|
删除目录
fs.rmdir(path, callback)
- path - 文件路径
- callback - 回调函数,没有参数
|
|
GET/POST请求
表单提交到服务器一般都使用 GET/POST 请求
获取GET请求内容
node.js 中 url 模块中的 parse 函数提供了这个功能
|
|
使用 url.parse 方法来解析 URL 中的参数
|
|
获取 POST 请求内容
POST 请求的内容全部的都在请求体中,http.ServerRequest 并没有一个属性内容为请求体
|
|
实例表单通过 POST 提交并输出数据
|
|
工具模块
OS模块
提供了一些基本的系统操作函数
var os = require(“os”)
|
|
Path 模块
提供了一些用于处理文件路径的小工具
var path = require(“path”)
|
|
Net 模块
提供了一些用于底层的网络通信的小工具,包含了创建服务器/客户端的方法
var net = require(“net”)
net.Server通常用于创建一个 TCP 或本地服务器
net.Socket 对象是 TCP 或 UNIX Socket 的抽象
|
|
新开一个窗口,创建 client.js 文件
|
|
DNS 模块
DNS 模块用于解析域名
var dns = require(“dns”)
|
|
Domain 模块
Domain(域) 简化异步代码的异常处理,可以捕捉处理try catch无法捕捉的异常
var domain = require(“domain”)
Domain 模块可分为隐式绑定和显式绑定
- 隐式绑定: 把在domain上下文中定义的变量,自动绑定到domain对象
- 显式绑定: 把不是在domain上下文中定义的变量,以代码的方式绑定到domain对象
|
|
Web 模块
Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,Web服务器的基本功能就是提供Web信息浏览服务
只需支持HTTP协议、HTML文档格式及URL,与客户端的网络浏览器配合
web 服务器支持服务端的脚本语言(php、python、ruby)等,并通过脚本语言从数据库获取数据,将结果返回给客户端浏览器
目前最主流的三个Web服务器是Apache、Nginx、IIS
Web 应用架构
- Client - 客户端,一般指浏览器,浏览器可以通过 HTTP 协议向服务器请求数据
- Server - 服务端,一般指 Web 服务器,可以接收客户端请求,并向客户端发送响应数据
- Business - 业务层, 通过 Web 服务器处理应用程序,如与数据库交互,逻辑运算,调用外部程序等
- Data - 数据层,一般由数据库组成
Node 创建 Web 服务器
Node.js 提供了 http 模块,http 模块主要用于搭建 HTTP 服务端和客户端,使用 HTTP 服务器或客户端功能必须调用 http 模块
var http = require(‘http’);
|
|
打开地址:http://127.0.0.1:8080/index.html
|
|
Node 创建 Web 客户端
Node 创建 Web 客户端需要引入 http 模块
|
|
RESTful API
REST即表述性状态传递
表述性状态转移是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是RESTful
REST 通常使用 JSON 数据格式
REST 基本架构的四个方法
- GET - 用于获取数据
- PUT - 用于更新或添加数据
- DELETE - 用于删除数据
- POST - 用于添加数据
RESTful Web Services
基于 REST 架构的 Web Services 即是 RESTful
由于轻量级以及通过 HTTP 直接传输数据的特性,Web 服务的 RESTful 方法已经成为最常见的替代方法
可以使用各种语言(比如 Java 程序、Perl、Ruby、Python、PHP 和 Javascript[包括 Ajax])实现客户端
创建 RESTful
创建一个 json 数据资源文件 users.json
|
|
基于以上数据,我们创建以下 RESTful API
| 序号 | URI | HTTP方法 | 发送内容 | 结果 |
|---|---|---|---|---|
| 1 | listUsers | GET | 空 | 显示所有用户列表 |
| 2 | addUser | POST | JSON 字符串 | 添加新用户 |
| 3 | deleteUser | DELETE | JSON 字符串 | 删除用户 |
| 4 | :id | GET | 空 | 显示用户详细信息 |
获取用户列表
创建了 RESTful API listUsers,用于读取用户的信息列表
|
|
添加用户
创建了 RESTful API addUser, 用于添加新的用户数据
|
|
显示用户详情
创建了 RESTful API :id(用户id), 用于读取指定用户的详细信息
|
|
删除用户
创建了 RESTful API deleteUser, 用于删除指定用户的详细信息
|
|
多进程
Node.js 是以单线程的模式运行的,但它使用的是事件驱动来处理并发
每个子进程总是带有三个流对象:child.stdin, child.stdout 和child.stderr
Node 提供了 child_process 模块来创建子进程,方法有
- exec - child_process.exec 使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式返回
- spawn - child_process.spawn 使用指定的命令行参数创建新进程
- fork - child_process.fork 是 spawn()的特殊形式,用于在子进程中运行的模块,如 fork(‘./son.js’) 相当于 spawn(‘node’, [‘./son.js’])
exec() 方法
child_process.exec 使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式返回
exec() 方法返回最大的缓冲区,并等待进程结束,一次性返回缓冲区的内容
child_process.exec(command[, options], callback)
- command: 字符串, 将要运行的命令,参数使用空格隔开
- options :对象
- callback :回调函数,包含三个参数error, stdout 和 stderr
|
|
spawn() 方法
child_process.spawn 使用指定的命令行参数创建新进程
spawn() 方法返回流 (stdout & stderr),在进程返回大量数据时使用。进程一旦开始执行时 spawn() 就开始接收响应
child_process.spawn(command[, args][, options])
- command: 将要运行的命令
- args: Array 字符串参数数组
- options Object
|
|
fork 方法
child_process.fork 是 spawn() 方法的特殊形式,用于创建进程
返回的对象除了拥有ChildProcess实例的所有方法,还有一个内建的通信信道
child_process.fork(modulePath[, args][, options])
- modulePath: String,将要在子进程中运行的模块
- args: Array 字符串参数数组
- options:Object
|
|
JXcore打包
JXcore 是一个支持多线程的 Node.js 发行版本
JXcore安装
下载 JXcore 安装包,并解压,在解压的的目录下提供了 jx 二进制文件命令
包代码
Node.js 项目包含以下几个文件,其中 index.js 是主文件
|
|
使用 jx 命令打包以上项目,并指定 index.js 为 Node.js 项目的主文件
|
|
命令执行成功,会生成以下两个文件
- index.jxp 这是一个中间件文件,包含了需要编译的完整项目信息
- index.jx 这是一个完整包信息的二进制文件,可运行在客户端上
载入 JX 文件
Node.js 的项目运行
|
|
使用 JXcore 编译后,我们可以使用以下命令来执行生成的 jx 二进制文件
|
|
连接 MySQL
略
连接 MongoDB
略