目录
1. Hello World
2. 创建第一个Node.js应用
3. REPL (调试Javascript)
4. 回调函数
5. 事件循环
6. 函数
7. 模块系统
8. 路由
少壮不努力,老大徒伤悲。
本文为本人略读官网文档后的大略笔记,实在不适合他人阅读。
前言
Node.js : 运行在服务端的JavaScript
是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎。
安装
安装node
brew install node
查看当前node版本
node -v
1. Hello World
创建test.js (内容如下)
console.log("Hello World");
终端执行 node test.js
输出Hello World
2. 创建第一个Node.js应用
Node.js应用的组成部分
1. 引入required模块
使用require指令来载入Node.js模块。
2. 创建服务器
服务器监听客户端请求。
Apache、Nginx等HTTP 服务器。
3. 接收请求与响应请求
客户端可以使用浏览器或终端发送HTTP请求,服务器接收请求后返回响应数据。
步骤1: 引入required模块
// 使用require指令载入http 模块,并将实例化的HTTP赋值给变量http
var http = require("http");
步骤2: 创建服务器
创建 server.js文件
var http = require('http');
// 创建服务器
http.createServer(function (request, response) {
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应数据 "Hello World"
response.end('Hello World\n');
}).listen(8088);
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8088/');
终端运行 node server.js
如果运行出错,可能是端口号冲突,换一个端口即可。
3. REPL (调试Javascript)
REPL(Read Eval Print Loop:交互式解释器)
一个电脑的环境,类似 Window 系统的终端或 Unix/Linux shell,我们可以在终端中输入命令,并接收系统的响应。
Node自带了交互式解释器,可以执行以下任务:
1. 读取
读取用户输入,解析输入了Javascript 数据结构并存储在内存中。
2. 执行
执行输入的数据结构
3. 打印
输出结果
4. 循环
循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。
退出当前终端
ctrl + c 。
按下两次 - 退出 Node REPL
ctrl + c 。
退出 Node REPL
ctrl + d -
查看输入的历史命令
向上/向下键
补全当前命令
tab 键
列出可使用命令
.help
退出多行表达式
.break
退出多行表达式
.clear
保存当前的 Node REPL 会话到指定文件
.save filename
载入当前 Node REPL 会话的文件内容
.load filename
首先,在终端输入node
可使用
1. 表达式运算
2. 变量
3. 多行语句
4. _获取上一个表达式的值
4. 回调函数
Node 所有 API 都支持回调函数
回调函数一般作为函数的最后一个参数出现
function foo1(name, age, callback) { }
function foo2(value, callback1, callback2) { }
例1 (阻塞)
创建content.txt文件
Hello World!
Hello cx,,,
创建main.js文件
var fs = require("fs");
var data = fs.readFileSync('content.txt');
console.log(data.toString());
console.log("程序执行结束!");
终端执行 node main.js
Hello World!
Hello cx,,,
程序执行结束!
例2 (非阻塞)
创建content.txt文件
Hello World!
Hello cx,,,
创建main.js文件
var fs = require("fs");
fs.readFile('content.txt', function (err, data) {
if (err) return console.error(err);
console.log(data.toString());
});
console.log("程序执行结束!");
终端执行 node main.js
程序执行结束!
Hello World!
Hello cx,,,
5. 事件循环
NOde.js是单进程单线程应用程序,但V8引擎提供了异步执行回调接口,可处理大量的并发,所以性能非常高。
几乎所有API都支持回调函数。
几乎所有事件机制都是通过观察者模式实现的。
第一步:导入事件模块,创建eventEmitter 对象
第二步:绑定事件
回调函数作为最后一个参数。
err对象作为回调函数第一个参数。
当添加新的监听器时,newListener 事件会触发。
当监听器被移除时,removeListener 事件被触发。
第三步:触发事件
类似于观察者模式,所有注册在某一事件上的处理函数都相当于观察者。当事件触发时依次调用处理函数。
// 1
// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
// 2
// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);
// 3
// 触发事件
eventEmitter.emit('eventName');
例1
创建test.js文件(内容如下)
执行node test.js 输出:
连接成功。
数据接收成功。
程序执行完毕。
// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象(在实例化时发生错误,会触发 error 事件)
var eventEmitter = new events.EventEmitter();
// 创建事件处理程序
var connectHandler = function connected() {
console.log('连接成功。');
// 触发 data_received 事件
eventEmitter.emit('data_received');
}
// 绑定 connection 事件处理程序
eventEmitter.on('connection', connectHandler);
// 使用匿名函数绑定 data_received 事件
eventEmitter.on('data_received', function(){
console.log('数据接收成功。');
});
// 触发 connection 事件
eventEmitter.emit('connection');
console.log("程序执行完毕。");
例2(err:回调函数的第一个参数)
============== input.txt ==============
Hello World!
Hello cx,,,
============== test.js ==============
var fs = require("fs");
fs.readFile('input.txt', function (err, data) {
if (err){
console.log(err.stack);
return;
}
console.log(data.toString());
});
console.log("程序执行完毕");
============== node test.js ==============
程序执行完毕
Hello World!
Hello cx,,,
==============删除input.txt node test.js ==============
程序执行完毕
Error: ENOENT: no such file or directory, open 'input.txt'
例3
输出:
listener1 arg1 参数 arg2 参数
listener2 arg1 参数 arg2 参数
//event.js 文件
var events = require('events');
var emitter = new events.EventEmitter();
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener1', arg1, arg2);
});
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener2', arg1, arg2);
});
emitter.emit('someEvent', 'arg1 参数', 'arg2 参数');
- EventEmitter
多数情况下不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。
通过require("events");导入events模块。
events模块只提供了一个对象,就是events.EventEmitter。
EventEmitter的核心就是对事件触发与事件监听器功能进行封装。
EventEmitter的每个事件由一个事件名和若干个参数组成。事件名是一个字符串。
Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列。
Node.js 里面的许多对象都会分发事件:
一个 net.Server 对象会在每次有新连接时触发一个事件
一个 fs.readStream 对象会在文件被打开的时候触发一个事件。
所有这些产生事件的对象都是 events.EventEmitter 的实例。
方法名 | 描述 | 例 |
---|---|---|
addListener(event, listener) | 为指定事件添加一个监听器(添加到监听器数组的尾部)。 | |
on(event, listener) | 为指定事件注册一个监听器(接受一个字符串 event 和一个回调函数)。 | server.on('connection', function (stream) { console.log('someone connected!'); }); |
once(event, listener) | 为指定事件注册一个单次监听器(即监听器最多只会触发一次,触发后立刻解除该监听器)。 | server.once('connection', function (stream) { console.log('Ah, we have our first user!'); }); |
removeListener(event, listener) | 移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器。它接受两个参数,第一个是事件名称,第二个是回调函数名称。 | var callback = function(stream) { console.log('someone connected!'); }; server.on('connection', callback); server.removeListener('connection', callback); |
removeAllListeners([event]) | 移除所有事件的所有监听器, 如果指定事件,则移除指定事件的所有监听器。 | |
setMaxListeners(n) | 默认情况下, EventEmitters添加的监听器超过 10 个就会输出警告信息。 setMaxListeners 函数用于提高监听器的默认限制的数量。 | |
listeners(event) | 返回指定事件的监听器数组。 | |
emit(event, [arg1], [arg2], [...]) | 按监听器的顺序执行执行每个监听器,如果事件有注册监听返回 true,否则返回 false。 | |
listenerCount(emitter, event) | 类方法。返回指定事件的监听器数量。 | events.EventEmitter.listenerCount(emitter, eventName) //已废弃,不推荐 events.emitter.listenerCount(eventName) //推荐 |
事件 | 描述 | 例 |
---|---|---|
newListener | event - 字符串,事件名称。listener - 处理事件函数。该事件在添加新监听器时被触发。 | |
removeListener | event - 字符串,事件名称。listener - 处理事件函数。从指定监听器数组中删除一个监听器。需要注意的是,此操作将会改变处于被删监听器之后的那些监听器的索引。 | |
error 事件 | 在遇到 异常的时候通常会触发 error 事件。如果没有响 应的监听器,Node.js 会把它当作异常,退出程序并输出错误信息。一般要为会触发 error 事件的对象设置监听器,避免遇到错误后整个程序崩溃。 | var events = require('events'); var emitter = new events.EventEmitter(); emitter.emit('error'); |
例1
输出
2 个监听器监听连接事件。
监听器 listener1 执行。
监听器 listener2 执行。
listener1 不再受监听。
监听器 listener2 执行。
1 个监听器监听连接事件。
程序执行完毕。
var events = require('events');
var eventEmitter = new events.EventEmitter();
// 监听器 #1
var listener1 = function listener1() {
console.log('监听器 listener1 执行。');
}
// 监听器 #2
var listener2 = function listener2() {
console.log('监听器 listener2 执行。');
}
// 绑定 connection 事件,处理函数为 listener1
eventEmitter.addListener('connection', listener1);
// 绑定 connection 事件,处理函数为 listener2
eventEmitter.on('connection', listener2);
var eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " 个监听器监听连接事件。");
// 处理 connection 事件
eventEmitter.emit('connection');
// 移除监绑定的 listener1 函数
eventEmitter.removeListener('connection', listener1);
console.log("listener1 不再受监听。");
// 触发连接事件
eventEmitter.emit('connection');
eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " 个监听器监听连接事件。");
console.log("程序执行完毕。");
大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。
为什么要这样做呢?原因有两点:
首先,具有某个实体功能的对象实现事件符合语义, 事件的监听和发生应该是一个对象的方法。
其次 JavaScript 的对象机制是基于原型的,支持 部分多重继承,继承 EventEmitter 不会打乱对象原有的继承关系。
6. 函数
函数作参
在JavaScript中,一个函数可以作为另一个函数的参数。
function say(word) {
console.log(word);
}
function execute(someFunction, value) {
someFunction(value);
}
execute(say, "Hello");
匿名函数
function execute(someFunction, value) {
someFunction(value);
}
execute(function(word){ console.log(word) }, "Hello");
http.createServer方法就是传入了一个匿名函数
var http = require("http");
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(8888);
==================等价
function onRequest(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
7. 模块系统
模块是Node.js 应用程序的基本组成部分。
文件和模块是一一对应的,即:一个 Node.js 文件就是一个模块。这个文件可以是js代码、JSON 、编译过的C/C++ 扩展。
Node.js提供了exports、require两个对象,分别用于导出、导入。
exports
暴露属性和方法
module.exports
暴露对象
Node.js存在4类模块(原生模块和3种文件模块)
原生模块
http、fs、path等。
相对路径的文件模块
./mod或../mod。
绝对路径的文件模块
/pathtomodule/mod。
非原生模块的文件模块
mod。
在路径 Y 下执行 require(X) 语句执行顺序
1. 如果 X 是内置模块
a. 返回内置模块
b. 停止执行
2. 如果 X 以 '/' 开头
a. 设置 Y 为文件根路径
3. 如果 X 以 './' 或 '/' or '../' 开头
a. LOAD_AS_FILE(Y + X)
b. LOAD_AS_DIRECTORY(Y + X)
4. LOAD_NODE_MODULES(X, dirname(Y))
5. 抛出异常 "not found"
LOAD_AS_FILE(X)
1. 如果 X 是一个文件, 将 X 作为 JavaScript 文本载入并停止执行。
2. 如果 X.js 是一个文件, 将 X.js 作为 JavaScript 文本载入并停止执行。
3. 如果 X.json 是一个文件, 解析 X.json 为 JavaScript 对象并停止执行。
4. 如果 X.node 是一个文件, 将 X.node 作为二进制插件载入并停止执行。
LOAD_INDEX(X)
1. 如果 X/index.js 是一个文件, 将 X/index.js 作为 JavaScript 文本载入并停止执行。
2. 如果 X/index.json 是一个文件, 解析 X/index.json 为 JavaScript 对象并停止执行。
3. 如果 X/index.node 是一个文件, 将 X/index.node 作为二进制插件载入并停止执行。
LOAD_AS_DIRECTORY(X)
1. 如果 X/package.json 是一个文件,
a. 解析 X/package.json, 并查找 "main" 字段。
b. let M = X + (json main 字段)
c. LOAD_AS_FILE(M)
d. LOAD_INDEX(M)
2. LOAD_INDEX(X)
LOAD_NODE_MODULES(X, START)
1. let DIRS=NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
a. LOAD_AS_FILE(DIR/X)
b. LOAD_AS_DIRECTORY(DIR/X)
NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = []
4. while I >= 0,
a. if PARTS[I] = "node_modules" CONTINUE
b. DIR = path join(PARTS[0 .. I] + "node_modules")
c. DIRS = DIRS + DIR
d. let I = I - 1
5. return DIRS
例1(创建模块)
================ hello.js ================
// 导出world
exports.world = function() {
console.log('Hello World');
}
================ test.js ================
// ./ 为当前目录,node.js 默认后缀为 js
var hello = require('./hello');
hello.world();
例2(当只导出一个对象时)
module.exports = function() {
// ...
}
如:http模块
var http = require("http");
http.createServer(...);
================ hello.js ================
//hello.js
function Hello() {
var name;
this.setName = function(thyName) {
name = thyName;
};
this.sayHello = function() {
console.log('Hello ' + name);
};
};
module.exports = Hello;
================ main.js ================
//main.js
var Hello = require('./hello');
hello = new Hello();
hello.setName('BYVoid');
hello.sayHello();
8. 路由
. 工具 模块
- OS 模块(系统操作函数)
引入
var os = require("os")
函数 | 说明 |
---|---|
os.tmpdir() | 返回操作系统的默认临时文件夹。 |
os.endianness() | 返回 CPU 的字节序,可能的是 "BE" 或 "LE"。 |
os.hostname() | 返回操作系统的主机名。 |
os.type() | 返回操作系统名 |
os.platform() | 返回编译时的操作系统名 |
os.arch() | 返回操作系统 CPU 架构,可能的值有 "x64"、"arm" 和 "ia32"。 |
os.release() | 返回操作系统的发行版本。 |
os.uptime() | 返回操作系统运行的时间,以秒为单位。 |
os.loadavg() | 返回一个包含 1、5、15 分钟平均负载的数组。 |
os.totalmem() | 返回系统内存总量,单位为字节。 |
os.freemem() | 返回操作系统空闲内存量,单位是字节。 |
os.cpus() | 返回一个对象数组,包含所安装的每个 CPU/内核的信息:型号、速度(单位 MHz)、时间(一个包含 user、nice、sys、idle 和 irq 所使用 CPU/内核毫秒数的对象)。 |
os.networkInterfaces() | 获得网络接口列表。 |
属性 | 说明 |
---|---|
os.EOL | 定义了操作系统的行尾符的常量 |
例1 (test.js)
var os = require("os");
// CPU 的字节序
console.log('endianness : ' + os.endianness());
// 操作系统名
console.log('type : ' + os.type());
// 操作系统名
console.log('platform : ' + os.platform());
// 系统内存总量
console.log('total memory : ' + os.totalmem() + " bytes.");
// 操作系统空闲内存量
console.log('free memory : ' + os.freemem() + " bytes.");
node test.js输出
endianness : LE
type : Darwin
platform : darwin
total memory : 17179869184 bytes.
free memory : 562544640 bytes.
- Path 模块 (处理文件路径的小工具)
引入
var path = require("path")
函数 | 说明 |
---|---|
path.normalize(p) | 规范化路径,注意'..' 和 '.'。 |
path.join([path1][, path2][, ...]) | 用于连接路径。该方法的主要用途在于,会正确使用当前系统的路径分隔符,Unix系统是"/",Windows系统是""。 |
path.resolve([from ...], to) | 将 to 参数解析为绝对路径,给定的路径的序列是从右往左被处理的,后面每个 path 被依次解析,直到构造完成一个绝对路径。 例如,给定的路径片段的序列为:/foo、/bar、baz,则调用 path.resolve('/foo', '/bar', 'baz') 会返回 /bar/baz。 |
path.isAbsolute(path) | 判断参数 path 是否是绝对路径。 |
path.relative(from, to) | 用于将绝对路径转为相对路径,返回从 from 到 to 的相对路径(基于当前工作目录)。 |
path.dirname(p) | 返回路径中代表文件夹的部分,同 Unix 的dirname 命令类似。 |
path.basename(p[, ext]) | 返回路径中的最后一部分。同 Unix 命令 bashname 类似。 |
path.extname(p) | 返回路径中文件的后缀名,即路径中最后一个'.'之后的部分。如果一个路径中并不包含'.'或该路径只包含一个'.' 且这个'.'为路径的第一个字符,则此命令返回空字符串。 |
path.parse(pathString) | 返回路径字符串的对象。 |
path.format(pathObject) | 从对象中返回路径字符串,和 path.parse 相反。 |
属性 | 说明 |
---|---|
path.sep | 平台的文件路径分隔符,'\' 或 '/'。 |
path.delimiter | 平台的分隔符, ; or ':'. |
path.posix | 提供上述 path 的方法,不过总是以 posix 兼容的方式交互。 |
path.win32 | 提供上述 path 的方法,不过总是以 win32 兼容的方式交互。 |
path.resolve([from ...], to) 例:
// 返回: '/foo/bar/baz'
path.resolve('/foo/bar', './baz');
// 返回: '/tmp/file'
path.resolve('/foo/bar', '/tmp/file/');
// 如果当前工作目录为 /home/myself/node,则返回 '/home/myself/node/wwwroot/static_files/gif/image.gif'
path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
path.relative(from, to)
在 Linux 上:
path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb');
// 返回: '../../impl/bbb'
在 Windows 上:
path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb');
// 返回: '..\\..\\impl\\bbb'
例1(test.js)
var path = require("path");
// 格式化路径
console.log('normalization : ' + path.normalize('/test/test1//2slashes/1slash/tab/..'));
// 连接路径
console.log('joint path : ' + path.join('/test', 'test1', '2slashes/1slash', 'tab', '..'));
// 转换为绝对路径
console.log('resolve : ' + path.resolve('main.js'));
// 路径中文件的后缀名
console.log('ext name : ' + path.extname('main.js'));
ode test.js输出
normalization : /test/test1/2slashes/1slash
joint path : /test/test1/2slashes/1slash
resolve : /Users/cx/Desktop/nodejs/main.js
ext name : .js
- Net 模块(用于底层的网络通信的小工具,包含了创建服务器/客户端的方法)
引入
var net = require("net")
函数 | 说明 |
---|---|
net.createServer([options][, connectionListener]) | 创建一个 TCP 服务器。参数 connectionListener 自动给 'connection' 事件创建监听器。 |
net.connect(options[, connectionListener]) | 返回一个新的 'net.Socket',并连接到指定的地址和端口。当 socket 建立的时候,将会触发 'connect' 事件。 |
net.createConnection(options[, connectionListener]) | 创建一个到端口 port 和 主机 host的 TCP 连接。 host 默认为 'localhost'。 |
net.connect(port[, host][, connectListener]) | 创建一个端口为 port 和主机为 host的 TCP 连接 。host 默认为 'localhost'。参数 connectListener 将会作为监听器添加到 'connect' 事件。返回 'net.Socket'。 |
net.createConnection(port[, host][, connectListener]) | 创建一个端口为 port 和主机为 host的 TCP 连接 。host 默认为 'localhost'。参数 connectListener 将会作为监听器添加到 'connect' 事件。返回 'net.Socket'。 |
net.connect(path[, connectListener]) | 创建连接到 path 的 unix socket 。参数 connectListener 将会作为监听器添加到 'connect' 事件上。返回 'net.Socket'。 |
net.createConnection(path[, connectListener]) | 创建连接到 path 的 unix socket 。参数 connectListener 将会作为监听器添加到 'connect' 事件。返回 'net.Socket'。 |
net.isIP(input) | 检测输入的是否为 IP 地址。 IPV4 返回 4, IPV6 返回 6,其他情况返回 0。 |
net.isIPv4(input) | 如果输入的地址为 IPV4, 返回 true,否则返回 false。 |
net.isIPv6(input) | 如果输入的地址为 IPV6, 返回 true,否则返回 false。 |
》》》net.Server
通常用于创建一个 TCP 或本地服务器
函数 | 说明 |
---|---|
erver.listen(port[, host][, backlog][, callback]) | 监听指定端口 port 和 主机 host ac连接。 默认情况下 host 接受任何 IPv4 地址(INADDR_ANY)的直接连接。端口 port 为 0 时,则会分配一个随机端口。 |
server.listen(path[, callback]) | 通过指定 path 的连接,启动一个本地 socket 服务器。 |
server.listen(handle[, callback]) | 通过指定句柄连接。 |
server.listen(options[, callback]) | options 的属性:端口 port, 主机 host, 和 backlog, 以及可选参数 callback 函数, 他们在一起调用server.listen(port, [host], [backlog], [callback])。还有,参数 path 可以用来指定 UNIX socket。 |
server.close([callback]) | 服务器停止接收新的连接,保持现有连接。这是异步函数,当所有连接结束的时候服务器会关闭,并会触发 'close' 事件。 |
server.address() | 操作系统返回绑定的地址,协议族名和服务器端口。 |
server.unref() | 如果这是事件系统中唯一一个活动的服务器,调用 unref 将允许程序退出。 |
server.ref() | 与 unref 相反,如果这是唯一的服务器,在之前被 unref 了的服务器上调用 ref 将不会让程序退出(默认行为)。如果服务器已经被 ref,则再次调用 ref 并不会产生影响。 |
server.getConnections(callback) | 异步获取服务器当前活跃连接的数量。当 socket 发送给子进程后才有效;回调函数有 2 个参数 err 和 count。 |
事件 | 说明 |
---|---|
listening | 当服务器调用 server.listen 绑定后会触发。 |
connection | 当新连接创建后会被触发。socket 是 net.Socket实例。 |
close | 服务器关闭时会触发。注意,如果存在连接,这个事件不会被触发直到所有的连接关闭。 |
error | 发生错误时触发。'close' 事件将被下列事件直接调用。 |
》》》net.Socket
net.Socket对象是 TCP 或 UNIX Socket 的抽象。
net.Socket 实例实现了一个双工流接口。
他们可以在用户创建客户端(使用 connect())时使用, 或者由 Node 创建它们,并通过 connection 服务器事件传递给用户。
方法 | 说明 |
---|---|
new net.Socket([options]) | 构造一个新的 socket 对象。 |
socket.connect(port[, host][, connectListener]) | 指定端口 port 和 主机 host,创建 socket 连接 。参数 host 默认为 localhost。通常情况不需要使用 net.createConnection 打开 socket。只有你实现了自己的 socket 时才会用到。 |
socket.connect(path[, connectListener]) | 打开指定路径的 unix socket。通常情况不需要使用 net.createConnection 打开 socket。只有你实现了自己的 socket 时才会用到。 |
socket.setEncoding([encoding]) | 设置编码 |
socket.write(data[, encoding][, callback]) | 在 socket 上发送数据。第二个参数指定了字符串的编码,默认是 UTF8 编码。 |
socket.end([data][, encoding]) | 半关闭 socket。例如,它发送一个 FIN 包。可能服务器仍在发送数据。 |
socket.destroy() | 确保没有 I/O 活动在这个套接字上。只有在错误发生情况下才需要。(处理错误等等)。 |
socket.pause() | 暂停读取数据。就是说,不会再触发 data 事件。对于控制上传非常有用。 |
socket.resume() | 调用 pause() 后想恢复读取数据。 |
socket.setTimeout(timeout[, callback]) | socket 闲置时间超过 timeout 毫秒后 ,将 socket 设置为超时。 |
socket.setNoDelay([noDelay]) | 禁用纳格(Nagle)算法。默认情况下 TCP 连接使用纳格算法,在发送前他们会缓冲数据。将 noDelay 设置为 true 将会在调用 socket.write() 时立即发送数据。noDelay 默认值为 true。 |
socket.setKeepAlive([enable][, initialDelay] | 禁用/启用长连接功能,并在发送第一个在闲置 socket 上的长连接 probe 之前,可选地设定初始延时。默认为 false。 设定 initialDelay (毫秒),来设定收到的最后一个数据包和第一个长连接probe之间的延时。将 initialDelay 设为0,将会保留默认(或者之前)的值。默认值为0. |
socket.address() | 操作系统返回绑定的地址,协议族名和服务器端口。返回的对象有 3 个属性,比如{ port: 12346, family: 'IPv4', address: '127.0.0.1' }。 |
socket.unref() | 如果这是事件系统中唯一一个活动的服务器,调用 unref 将允许程序退出。如果服务器已被 unref,则再次调用 unref 并不会产生影响。 |
socket.ref() | 与 unref 相反,如果这是唯一的服务器,在之前被 unref 了的服务器上调用 ref 将不会让程序退出(默认行为)。如果服务器已经被 ref,则再次调用 ref 并不会产生影响。 |
属性 | 说明 |
---|---|
socket.bufferSize | 该属性显示了要写入缓冲区的字节数。 |
socket.remoteAddress | 远程的 IP 地址字符串,例如:'74.125.127.100' or '2001:4860:a005::68'。 |
socket.remoteFamily | 远程IP协议族字符串,比如 'IPv4' or 'IPv6'。 |
socket.remotePort | 远程端口,数字表示,例如:80 or 21。 |
socket.localAddress | 网络连接绑定的本地接口 远程客户端正在连接的本地 IP 地址,字符串表示。例如,如果你在监听'0.0.0.0'而客户端连接在'192.168.1.1',这个值就会是 '192.168.1.1'。 |
socket.localPort | 本地端口地址,数字表示。例如:80 or 21。 |
socket.bytesRead | 接收到得字节数。 |
socket.bytesWritten | 发送的字节数。 |
事件 | 说明 |
---|---|
ookup | 在解析域名后,但在连接前,触发这个事件。对 UNIX sokcet 不适用。 |
connect | 成功建立 socket 连接时触发。 |
data | 当接收到数据时触发。 |
end | 当 socket 另一端发送 FIN 包时,触发该事件。 |
timeout | 当 socket 空闲超时时触发,仅是表明 socket 已经空闲。用户必须手动关闭连接。 |
drain | 当写缓存为空得时候触发。可用来控制上传。 |
error | 错误发生时触发。 |
close | 当 socket 完全关闭时触发。参数 had_error 是布尔值,它表示是否因为传输错误导致 socket 关闭。 |
例1
============== server.js ===============
var net = require('net');
var server = net.createServer(function(connection) {
console.log('client connected');
connection.on('end', function() {
console.log('客户端关闭连接');
});
connection.write('Hello World!\r\n');
connection.pipe(connection);
});
server.listen(8088, function() {
console.log('server is listening');
});
============== client.js ===============
var net = require('net');
var client = net.connect({port: 8088}, function() {
console.log('连接到服务器!');
});
client.on('data', function(data) {
console.log(data.toString());
client.end();
});
client.on('end', function() {
console.log('断开与服务器的连接');
});
============== 在两个终端下分别执行 node server.js、node client.js ===============
服务端输出
server is listening
client connected
客户端关闭连接
客户端输出
连接到服务器!
Hello World!
断开与服务器的连接
- DNS 模块 (解析域名)
引入
var dns = require("dns")
函数 | 说明 |
---|---|
dns.lookup(hostname[, options], callback) | 将域名(比如 'runoob.com')解析为第一条找到的记录 A (IPV4)或 AAAA(IPV6)。参数 options可以是一个对象或整数。如果没有提供 options,IP v4 和 v6 地址都可以。如果 options 是整数,则必须是 4 或 6。 |
dns.lookupService(address, port, callback) | 使用 getnameinfo 解析传入的地址和端口为域名和服务。 |
dns.resolve(hostname[, rrtype], callback) | 将一个域名(如 'runoob.com')解析为一个 rrtype 指定记录类型的数组。 |
dns.resolve4(hostname, callback) | 和 dns.resolve() 类似, 仅能查询 IPv4 (A 记录)。 addresses IPv4 地址数组 (比如,['74.125.79.104', '74.125.79.105', '74.125.79.106'])。 |
dns.resolve6(hostname, callback) | 和 dns.resolve4() 类似, 仅能查询 IPv6( AAAA 查询) |
dns.resolveMx(hostname, callback) | 和 dns.resolve() 类似, 仅能查询邮件交换(MX 记录)。 |
dns.resolveTxt(hostname, callback) | 和 dns.resolve() 类似, 仅能进行文本查询 (TXT 记录)。 addresses 是 2-d 文本记录数组。(比如,[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ])。 每个子数组包含一条记录的 TXT 块。根据使用情况可以连接在一起,也可单独使用。 |
dns.resolveSrv(hostname, callback) | 和 dns.resolve() 类似, 仅能进行服务记录查询 (SRV 记录)。 addresses 是 hostname可用的 SRV 记录数组。 SRV 记录属性有优先级(priority),权重(weight), 端口(port), 和名字(name) (比如,[{'priority': 10, 'weight': 5, 'port': 21223, 'name': 'service.example.com'}, ...])。 |
dns.resolveSoa(hostname, callback) | 和 dns.resolve() 类似, 仅能查询权威记录(SOA 记录)。 |
dns.resolveNs(hostname, callback) | 和 dns.resolve() 类似, 仅能进行域名服务器记录查询(NS 记录)。 addresses 是域名服务器记录数组(hostname 可以使用) (比如, ['ns1.example.com', 'ns2.example.com'])。 |
dns.resolveCname(hostname, callback) | 和 dns.resolve() 类似, 仅能进行别名记录查询 (CNAME记录)。addresses 是对 hostname 可用的别名记录数组 (比如,, ['bar.example.com'])。 |
dns.reverse(ip, callback) | 反向解析 IP 地址,指向该 IP 地址的域名数组。 |
dns.getServers() | 返回一个用于当前解析的 IP 地址数组的字符串。 |
dns.setServers(servers) | 指定一组 IP 地址作为解析服务器。 |
dns.resolve() 方法中有效的 rrtypes值:
'A' IPV4 地址, 默认
'AAAA' IPV6 地址
'MX' 邮件交换记录
'TXT' text 记录
'SRV' SRV 记录
'PTR' 用来反向 IP 查找
'NS' 域名服务器记录
'CNAME' 别名记录
'SOA' 授权记录的初始值
每次 DNS 查询都可能返回以下错误码:
dns.NODATA: 无数据响应。
dns.FORMERR: 查询格式错误。
dns.SERVFAIL: 常规失败。
dns.NOTFOUND: 没有找到域名。
dns.NOTIMP: 未实现请求的操作。
dns.REFUSED: 拒绝查询。
dns.BADQUERY: 查询格式错误。
dns.BADNAME: 域名格式错误。
dns.BADFAMILY: 地址协议不支持。
dns.BADRESP: 回复格式错误。
dns.CONNREFUSED: 无法连接到 DNS 服务器。
dns.TIMEOUT: 连接 DNS 服务器超时。
dns.EOF: 文件末端。
dns.FILE: 读文件错误。
dns.NOMEM: 内存溢出。
dns.DESTRUCTION: 通道被摧毁。
dns.BADSTR: 字符串格式错误。
dns.BADFLAGS: 非法标识符。
dns.NONAME: 所给主机不是数字。
dns.BADHINTS: 非法HINTS标识符。
dns.NOTINITIALIZED: c c-ares 库尚未初始化。
dns.LOADIPHLPAPI: 加载 iphlpapi.dll 出错。
dns.ADDRGETNETWORKPARAMS: 无法找到 GetNetworkParams 函数。
dns.CANCELLED: 取消 DNS 查询。
例1(test.js)
var dns = require('dns');
dns.lookup('www.github.com', function onLookup(err, address, family) {
console.log('ip 地址:', address);
dns.reverse(address, function (err, hostnames) {
if (err) {
console.log(err.stack);
}
console.log('反向解析 ' + address + ': ' + JSON.stringify(hostnames));
});
});
node test.js输出
ip 地址: 13.250.177.223
反向解析 13.250.177.223: ["ec2-13-250-177-223.ap-southeast-1.compute.amazonaws.com"]
- Domain 模块 (捕捉处理try catch无法捕捉的异常)
引入
var domain = require("domain")
Domain 模块分为
1. 隐式绑定
把在domain上下文中定义的变量,自动绑定到domain对象
2. 显式绑定
把不是在domain上下文中定义的变量,以代码的方式绑定到domain对象
把处理多个不同的IO的操作作为一个组。注册事件和回调到domain,当发生一个错误事件或抛出一个错误时,domain对象会被通知,不会丢失上下文环境,也不导致程序错误立即退出,与process.on('uncaughtException')不同
函数 | 说明 |
---|---|
domain.run(function) | 在域的上下文运行提供的函数,隐式的绑定了所有的事件分发器,计时器和底层请求。 |
domain.add(emitter) | 显式的增加事件 |
domain.remove(emitter) | 删除事件。 |
domain.bind(callback) | 返回的函数是一个对于所提供的回调函数的包装函数。当调用这个返回的函数时,所有被抛出的错误都会被导向到这个域的 error 事件。 |
domain.intercept(callback) | 和 domain.bind(callback) 类似。除了捕捉被抛出的错误外,它还会拦截 Error 对象作为参数传递到这个函数。 |
domain.enter() | 进入一个异步调用的上下文,绑定到domain。 |
domain.exit() | 退出当前的domain,切换到不同的链的异步调用的上下文中。对应domain.enter()。 |
domain.dispose() | 释放一个domain对象,让node进程回收这部分资源。 |
domain.create() | 返回一个domain对象。 |
属性 | 说明 |
---|---|
domain.members | 已加入domain对象的域定时器和事件发射器的数组。 |
例1(test.js)
var EventEmitter = require("events").EventEmitter;
var domain = require("domain");
var emitter1 = new EventEmitter();
// 创建域
var domain1 = domain.create();
domain1.on('error', function(err){
console.log("domain1 处理这个错误 ("+err.message+")");
});
// 显式绑定
domain1.add(emitter1);
emitter1.on('error',function(err){
console.log("监听器处理此错误 ("+err.message+")");
});
emitter1.emit('error',new Error('通过监听器来处理'));
emitter1.removeAllListeners('error');
emitter1.emit('error',new Error('通过 domain1 处理'));
var domain2 = domain.create();
domain2.on('error', function(err){
console.log("domain2 处理这个错误 ("+err.message+")");
});
// 隐式绑定
domain2.run(function(){
var emitter2 = new EventEmitter();
emitter2.emit('error',new Error('通过 domain2 处理'));
});
domain1.remove(emitter1);
emitter1.emit('error', new Error('转换为异常,系统将崩溃!'));
node test.js输出
监听器处理此错误 (通过监听器来处理)
domain1 处理这个错误 (通过 domain1 处理)
domain2 处理这个错误 (通过 domain2 处理)
events.js:298
throw er; // Unhandled 'error' event
^
Error: 转换为异常,系统将崩溃!
at Object.<anonymous> (/Users/cx/Desktop/nodejs/client.js:40:24)
at Module._compile (internal/modules/cjs/loader.js:1151:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1171:10)
at Module.load (internal/modules/cjs/loader.js:1000:32)
at Function.Module._load (internal/modules/cjs/loader.js:899:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47
Emitted 'error' event at:
at Object.<anonymous> (/Users/cx/Desktop/nodejs/client.js:40:10)
at Module._compile (internal/modules/cjs/loader.js:1151:30)
[... lines matching original stack trace ...]
at internal/main/run_main_module.js:17:47
- util 模块(Node.js核心)常用函数
引入
const util = require('util');
将 async 异步函数(或者一个返回值为 Promise 的函数)转换成遵循异常优先的回调风格的函数
// (err, value) => ... 回调,作为最后一个参数
// 在回调函数中,第一个参数为拒绝的原因(如果 Promise 解决,则为 null),第二个参数则是解决的值。
util.callbackify(original)
例1
const util = require('util');
async function fn() {
return 'hello world';
}
const callbackFunction = util.callbackify(fn);
callbackFunction((err, ret) => {
if (err) throw err;
console.log(ret);
});
输出
hello world
例2
function fn() {
return Promise.reject(null);
}
const callbackFunction = util.callbackify(fn);
callbackFunction((err, ret) => {
// 当 Promise 被以 `null` 拒绝时,它被包装为 Error 并且原始值存储在 `reason` 中。
err && err.hasOwnProperty('reason') && err.reason === null; // true
});
实现对象间原型继承的函数
util.inherits(constructor, superConstructor)
JavaScript 的面向对象特性是基于原型的,与常见的基于类的不同。JavaScript 没有提供对象继承的语言级别特性,而是通过原型复制来实现的。
例
============= test.js =============
var util = require('util');
function Base() {
this.name = 'cx';
this.base = 2000;
this.sayHello = function() {
console.log('Hello ' + this.name);
};
}
Base.prototype.showName = function() {
console.log(this.name);
};
function Sub() {
this.name = 'sub';
}
util.inherits(Sub, Base);
var objBase = new Base();
objBase.showName();
objBase.sayHello();
console.log(objBase);
var objSub = new Sub();
objSub.showName();
//objSub.sayHello();
console.log(objSub);
=============终端输出=============
cx
Hello cx
Base { name: 'cx', base: 2000, sayHello: [Function (anonymous)] }
sub
Sub { name: 'sub' }
=============注意=============
Sub 仅仅继承了Base 在原型中定义的函数,而构造函数内部创造的 base 属 性和 sayHello 函数都没有被 Sub 继承。
在原型中定义的属性不会被 console.log 作 为对象的属性输出。
将任意对象转换为字符串
// object 要转换的对象
// showHidden 是否显示隐藏信息
// depth 最大递归的层数,默认2层,null则表示不限递归层数完整遍历
// colors 以 ANSI 颜色编码,在终端显示更漂亮
util.inspect(object,[showHidden],[depth],[colors])
例
============= test.js =============
var util = require('util');
function Person() {
this.name = 'cx';
this.toString = function() {
return this.name;
};
}
var obj = new Person();
console.log(util.inspect(obj));
console.log(util.inspect(obj, true));
=============终端输出=============
Person { name: 'cx', toString: [Function (anonymous)] }
Person {
name: 'cx',
toString: <ref *1> [Function (anonymous)] {
[length]: 0,
[name]: '',
[arguments]: null,
[caller]: null,
[prototype]: { [constructor]: [Circular *1] }
}
}
是否是数组
util.isArray(object)
例
var util = require('util');
// true
util.isArray([])
// true
util.isArray(new Array)
// false
util.isArray({})
是否是正则表达式
util.isRegExp(object)
例
var util = require('util');
// true
util.isRegExp(/some regexp/)
// true
util.isRegExp(new RegExp('another regexp'))
// false
util.isRegExp({})
是否是日期
util.isDate(object)
例
var util = require('util');
// true
util.isDate(new Date())
// false (without 'new' returns a String)
util.isDate(Date())
// false
util.isDate({})
Web 模块
Node.js 提供了 http 模块。http 模块主要用于搭建 HTTP 服务端和客户端,使用 HTTP 服务器或客户端功能必须调用 http 模块。
var http = require('http');
- Web应用架构
Web服务器,目前最主流的3个: Apache、Nginx、IIS
Web应用架构说明
1. Client
客户端,一般指浏览器。浏览器可以通过 HTTP 协议向服务器请求数据。
2. Server
服务端,一般指 Web 服务器。可以接收客户端请求,并向客户端发送响应数据。
3. Business
业务层, 通过 Web 服务器处理应用程序,如与数据库交互,逻辑运算,调用外部程序等。
4. Data
数据层,一般由数据库组成。
- 例
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World</title>
</head>
<body>
<h1>我的第一个标题</h1>
<p>我的第一个段落。</p>
</body>
</html>
server.js 服务器 (同一目录下创建该文件)
var http = require('http');
var fs = require('fs');
var url = require('url');
// 创建服务器
http.createServer( function (request, response) {
// 解析请求,包括文件名
var pathname = url.parse(request.url).pathname;
// 输出请求的文件名
console.log("Request for " + pathname + " received.");
// 从文件系统中读取请求的文件内容
fs.readFile(pathname.substr(1), function (err, data) {
if (err) {
console.log(err);
// HTTP 状态码: 404 : NOT FOUND
// Content Type: text/html
response.writeHead(404, {'Content-Type': 'text/html'});
}else{
// HTTP 状态码: 200 : OK
// Content Type: text/html
response.writeHead(200, {'Content-Type': 'text/html'});
// 响应文件内容
response.write(data.toString());
}
// 发送响应数据
response.end();
});
}).listen(8088);
// 控制台会输出以下信息
console.log('Server running at http://127.0.0.1:8088/');
终端启动服务器:node server.js
终端输出:Request for /index.html received.
client.js 客户端
var http = require('http');
// 用于请求的选项
var options = {
host: 'localhost',
port: '8088',
path: '/index.html'
};
// 处理响应的回调函数
var callback = function(response){
// 不断更新数据
var body = '';
response.on('data', function(data) {
body += data;
});
response.on('end', function() {
// 数据接收完成
console.log(body);
});
}
// 向服务端发送请求
var req = http.request(options, callback);
req.end();
执行客户端:node client.js(新开一个终端)
服务端-终端会输出:
Request for /index.html received.
客户端-终端会输出html内容:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World</title>
</head>
<body>
<h1>我的第一个标题</h1>
<p>我的第一个段落。</p>
</body>
</html>
GET/POST请求
- 获取GET请求内容
server.js
var http = require('http');
var url = require('url');
var util = require('util');
http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
res.end(util.inspect(url.parse(req.url, true)));
}).listen(3000);
node server.js
server.js
var http = require('http');
var url = require('url');
var util = require('util');
http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
// 解析 url 参数
var params = url.parse(req.url, true).query;
res.write("name=" + params.name);
res.write("\n");
res.write("hello=" + params.hello);
res.end();
}).listen(3000);
node server.js
- 获取POST请求内容
POST 请求的内容全部的都在请求体中,http.ServerRequest 并没有一个属性内容为请求体,原因是等待请求体传输可能是一件耗时的工作。
比如上传文件,而很多时候我们可能并不需要理会请求体的内容,恶意的POST请求会大大消耗服务器的资源,所以 node.js 默认是不会解析请求体的,当你需要的时候,需要手动来做。
var http = require('http');
var querystring = require('querystring');
var util = require('util');
http.createServer(function(req, res){
// 定义了一个post变量,用于暂存请求体的信息
var post = '';
// 通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
req.on('data', function(chunk){
post += chunk;
});
// 在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
req.on('end', function(){
post = querystring.parse(post);
res.end(util.inspect(post));
});
}).listen(3000);
例1(server.js)
var http = require('http');
var querystring = require('querystring');
var postHTML =
'<html><head><meta charset="utf-8"><title>Hello World</title></head>' +
'<body>' +
'<form method="post">' +
'网站名: <input name="name"><br>' +
'网站 URL: <input name="url"><br>' +
'<input type="submit">' +
'</form>' +
'</body></html>';
http.createServer(function (req, res) {
var body = "";
req.on('data', function (chunk) {
body += chunk;
});
req.on('end', function () {
// 解析参数
body = querystring.parse(body);
// 设置响应头部信息及编码
res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
if(body.name && body.url) { // 输出提交的数据
res.write("网站名:" + body.name);
res.write("<br>");
res.write("网站 URL:" + body.url);
} else { // 输出表单
res.write(postHTML);
}
res.end();
});
}).listen(3000);
node server.js
多进程
引入
const child_process = require('child_process');
Node.js 是以单线程的模式运行的,但它使用的是事件驱动来处理并发,这样有助于在多核 cpu 的系统上创建多个子进程,从而提高性能。
每个子进程总是带有三个流对象:child.stdin,child.stdout 和child.stderr。他们可能会共享父进程的 stdio 流,或者也可以是独立的被导流的流对象。
- child_process.exec(command[, options], callback)
使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式返回
等待进程结束,一次性返回缓冲区的内容
command
将要执行的命令
是个字符串,参数使用空格隔开(例:'node support.js ')
options
参数
是个对象
1. cwd
子进程的当前工作目录
字符串
2. env
环境变量键值对
对象
3. encoding
字符编码(默认: 'utf8')
字符串
4. shell
将要执行命令的 Shell(默认: 在 UNIX 中为/bin/sh, 在 Windows 中为cmd.exe, Shell 应当能识别 -c开关在 UNIX 中,或 /s /c 在 Windows 中。 在Windows 中,命令行解析应当能兼容cmd.exe)
字符串
5. timeout
超时时间(默认: 0)
数字
6. maxBuffer
在 stdout 或 stderr 中允许存在的最大缓冲(二进制),如果超出那么子进程将会被杀死 (默认: 200*1024)
数字
7. killSignal
结束信号(默认:'SIGTERM')
字符串
8. uid
设置用户进程的 ID
数字
9. gid
设置进程组的 ID
数字
callback
回调函数
包含三个参数error, stdout 和 stderr。(例:function (error, stdout, stderr) {} )
例1
================ support.js ================
console.log("进程 " + process.argv[2] + " 执行。" );
================ test.js ================
const fs = require('fs');
const child_process = require('child_process');
for(var i=0; i<3; i++) {
var workerProcess = child_process.exec('node support.js '+i, function (error, stdout, stderr) {
if (error) {
console.log(error.stack);
console.log('Error code: '+error.code);
console.log('Signal received: '+error.signal);
}
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
});
workerProcess.on('exit', function (code) {
console.log('子进程已退出,退出码 '+code);
});
}
================ node test.js ================
子进程已退出,退出码 0
子进程已退出,退出码 0
子进程已退出,退出码 0
stdout: 进程 2 执行。
stderr:
stdout: 进程 1 执行。
stderr:
stdout: 进程 0 执行。
stderr:
- child_process.spawn(command[, args][, options])
使用指定的命令行参数创建新进程
返回流 (stdout & stderr),在进程返回大量数据时使用。进程一旦开始执行时 spawn() 就开始接收响应。
command
将要执行的命令
是个字符串
args
字符串参数数组
是个Array
options
是个Object
1. cwd
子进程的当前工作目录
String
2. env
环境变量键值对
Object
3. stdio
子进程的 stdio 配置
Array|String
4. detached
这个子进程将会变成进程组的领导
Boolean
5. uid
设置用户进程的 ID
Number
6. gid
设置进程组的 ID
Number
例1
================ support.js ================
console.log("进程 " + process.argv[2] + " 执行。" );
================ test.js ================
const fs = require('fs');
const child_process = require('child_process');
for(var i=0; i<3; i++) {
var workerProcess = child_process.spawn('node', ['support.js', i]);
workerProcess.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
workerProcess.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
workerProcess.on('close', function (code) {
console.log('子进程已退出,退出码 '+code);
});
}
================ node test.js ================
stdout: 进程 0 执行。
stdout: 进程 1 执行。
stdout: 进程 2 执行。
子进程已退出,退出码 0
子进程已退出,退出码 0
子进程已退出,退出码 0
- child_process.fork(modulePath[, args][, options])
spawn() 方法的特殊形式,用于创建进程。
如 fork('./son.js') 相当于 spawn('node', ['./son.js']) 。
与spawn方法不同的是,fork会在父进程与子进程之间,建立一个通信管道,用于进程之间的通信
modulePath
将要在子进程中运行的模块
String
args
字符串参数数组
Array
options
Object
1. cwd
子进程的当前工作目录
String
2. env
环境变量键值对
Object
3. execPath
创建子进程的可执行文件
String
4. execArgv
子进程的可执行文件的字符串参数数组(默认: process.execArgv)
Array
5. silent
如果为true,子进程的stdin,stdout和stderr将会被关联至父进程,
如果为false,它们将会从父进程中继承。(默认为:false)
Boolean
6. uid
设置用户进程的 ID
Number
7. gid
设置进程组的 ID
Number
================ support.js ================
console.log("进程 " + process.argv[2] + " 执行。" );
================ test.js ================
const fs = require('fs');
const child_process = require('child_process');
for(var i=0; i<3; i++) {
var worker_process = child_process.fork("support.js", [i]);
worker_process.on('close', function (code) {
console.log('子进程已退出,退出码 ' + code);
});
}
================ node test.js ================
进程 0 执行。
进程 1 执行。
进程 2 执行。
子进程已退出,退出码 0
子进程已退出,退出码 0
子进程已退出,退出码 0
JXcore(打包)
JXcore:一个支持多线程的Node.js发行版本
- 安装JXcore
1. 下载JXcore安装包
2. 解压后找到对应平台的zip包,解压后将jx可执行文件复制到/usr/local/bin目录下
3. export PATH=$PATH:/usr/local/bin
4. 查看是否安装成功(出现jx版本号,则成功)
jx --version
- 将项目打包成一个可运行的.jx文件
打包(指定 index.js 为 Node.js 项目的主文件)
jx package index.js index
会生成2文件
1. index.jxp。中间件文件,包含了需要编译的完整项目信息。
2. index.jx。完整包信息的二进制文件,可运行在客户端上。
运行
jx index.jx
Buffer(缓冲区)
JavaScript只有字符串数据类型,没有二进制数据类型。
但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。
在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。
Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。
原始数据存储在 Buffer 类的实例中。
一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。
在v6.0之前创建Buffer对象直接使用new Buffer()构造函数来创建对象实例,但是Buffer对内存的权限操作相比很大,可以直接捕获一些敏感信息,所以在v6.0以后,官方文档里面建议使用 Buffer.from() 接口去创建Buffer对象。
- Buffer 与字符编码
Buffer实例一般用于表示编码字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六进制编码的数据。
通过使用显式的字符编码,就可以在 Buffer 实例与普通的 JavaScript 字符串之间进行相互转换。
Node.js 目前支持的字符编码包括:
1. ascii
仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。
2. utf8
多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。
3. utf16le
2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。
4. ucs2
utf16le 的别名。
5. base64
Base64 编码。
6. latin1
一种把 Buffer 编码成一字节编码的字符串的方式。
7. binary
latin1 的别名。
8. hex
将每个字节编码为两个十六进制字符
例1
const buf = Buffer.from('cx', 'ascii');
// 输出 6378
console.log(buf.toString('hex'));
// 输出 Y3g=
console.log(buf.toString('base64'));
- 创建 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 实例
例1
// 创建一个长度为 10、且用 0 填充的 Buffer。
const buf1 = Buffer.alloc(10);
// 创建一个长度为 10、且用 0x1 填充的 Buffer。
const buf2 = Buffer.alloc(10, 1);
// 创建一个长度为 10、且未初始化的 Buffer。
// 这个方法比调用 Buffer.alloc() 更快,
// 但返回的 Buffer 实例可能包含旧数据,
// 因此需要使用 fill() 或 write() 重写。
const buf3 = Buffer.allocUnsafe(10);
// 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);
// 创建一个包含 UTF-8 字节 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。
const buf5 = Buffer.from('tést');
// 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
const buf6 = Buffer.from('tést', 'latin1');
- 写入缓冲区
buf.write(string[, offset[, length]][, encoding])
根据 encoding 的字符编码写入 string 到 buf 中的 offset 位置。
length 参数是写入的字节数。 如果 buf 没有足够的空间保存整个字符串,则只会写入 string 的一部分。 只部分解码的字符不会被写入。
返回实际写入的大小。如果 buffer 空间不足, 则只会写入部分字符串。
参数说明
1. string
写入缓冲区的字符串。
2. offset
缓冲区开始写入的索引值,默认为 0 。
3. length
写入的字节数,默认为 buffer.length
4. encoding
使用的编码。默认为 'utf8' 。
例1
buf = Buffer.alloc(256);
len = buf.write("www.baidu.com");
console.log("写入字节数 : "+ len);
================
写入字节数 : 13
- 从缓冲区读取数据
buf.toString([encoding[, start[, end]]])
解码缓冲区数据并使用指定的编码返回字符串。
参数说明
1. encoding
使用的编码。默认为 'utf8' 。
2. start
指定开始读取的索引位置,默认为 0。
3. end
结束位置,默认为缓冲区的末尾。
例1
buf = Buffer.alloc(26);
for (var i = 0 ; i < 26 ; i++) {
buf[i] = i + 97;
}
console.log( buf.toString('ascii')); // 输出: abcdefghijklmnopqrstuvwxyz
console.log( buf.toString('ascii',0,5)); //使用 'ascii' 编码, 并输出: abcde
console.log( buf.toString('utf8',0,5)); // 使用 'utf8' 编码, 并输出: abcde
console.log( buf.toString(undefined,0,5)); // 使用默认的 'utf8' 编码, 并输出: abcde
================
abcdefghijklmnopqrstuvwxyz
abcde
abcde
abcde
- 将 Buffer 转换为 JSON 对象
buf.toJSON()
当字符串化一个 Buffer 实例时,JSON.stringify() 会隐式地调用该 toJSON()。
例1
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);
// 输出: {"type":"Buffer","data":[1,2,3,4,5]}
console.log(json);
const copy = JSON.parse(json, (key, value) => {
return value && value.type === 'Buffer' ?
Buffer.from(value.data) :
value;
});
// 输出: <Buffer 01 02 03 04 05>
console.log(copy);
==================
{"type":"Buffer","data":[1,2,3,4,5]}
<Buffer 01 02 03 04 05>
- 缓冲区合并
Buffer.concat(list[, totalLength])
返回一个多个成员合并的新 Buffer 对象
参数说明
1. list
用于合并的 Buffer 对象数组列表。
2. totalLength
指定合并后Buffer对象的总长度。
例1
var buffer1 = Buffer.from(('hello'));
var buffer2 = Buffer.from(('world'));
var buffer3 = Buffer.concat([buffer1,buffer2]);
console.log("buffer3 内容: " + buffer3.toString());
=====================
buffer3 内容: helloworld
- 缓冲区比较
buf.compare(otherBuffer);
返回一个数字,表示 buf 在 otherBuffer 之前,之后或相同。
参数说明
1. otherBuffer
与 buf 对象比较的另外一个 Buffer 对象。
例1
var buffer1 = Buffer.from('ABC');
var buffer2 = Buffer.from('ABCD');
var result = buffer1.compare(buffer2);
if(result < 0) {
console.log(buffer1 + " 在 " + buffer2 + "之前");
}else if(result == 0){
console.log(buffer1 + " 与 " + buffer2 + "相同");
}else {
console.log(buffer1 + " 在 " + buffer2 + "之后");
}
======================
ABC 在 ABCD之前
- 拷贝缓冲区
buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])
参数说明
1. targetBuffer
要拷贝的 Buffer 对象。
2. targetStart
数字, 可选, 默认: 0
3. sourceStart
数字, 可选, 默认: 0
4. sourceEnd
数字, 可选, 默认: buffer.length
例1
var buf1 = Buffer.from('abcdefghijkl');
var buf2 = Buffer.from('RUNOOB');
//将 buf2 插入到 buf1 指定位置上
buf2.copy(buf1, 2);
console.log(buf1.toString());
===================
abRUNOOBijkl
- 缓冲区裁剪
buf.slice([start[, end]])
返回一个新的缓冲区,它和旧缓冲区指向同一块内存,但是从索引 start 到 end 的位置剪切。
参数说明
1. start
数字, 可选, 默认: 0
2. end
数字, 可选, 默认: buffer.length
例1
var buffer1 = Buffer.from('runoob');
// 剪切缓冲区
var buffer2 = buffer1.slice(0,2);
console.log("buffer2 content: " + buffer2.toString());
==================
buffer2 content: ru
- 缓冲区长度
buf.length;
返回 Buffer 对象所占据的内存长度
例1
var buffer = Buffer.from('hello world');
// 缓冲区长度
console.log("buffer length: " + buffer.length);
==================
buffer length: 11
方法 | 说明 |
---|---|
new Buffer(size) | 分配一个新的 size 大小单位为8位字节的 buffer。 注意, size 必须小于 kMaxLength,否则,将会抛出异常 RangeError。废弃的: 使用 Buffer.alloc() 代替(或 Buffer.allocUnsafe())。 |
new Buffer(buffer) | 拷贝参数 buffer 的数据到 Buffer 实例。废弃的: 使用 Buffer.from(buffer) 代替。 |
new Buffer(str[, encoding]) | 分配一个新的 buffer ,其中包含着传入的 str 字符串。 encoding 编码方式默认为 'utf8'。 废弃的: 使用 Buffer.from(string[, encoding]) 代替。 |
buf.length | 返回这个 buffer 的 bytes 数。注意这未必是 buffer 里面内容的大小。length 是 buffer 对象所分配的内存数,它不会随着这个 buffer 对象内容的改变而改变。 |
buf.write(string[, offset[, length]][, encoding]) | 根据参数 offset 偏移量和指定的 encoding 编码方式,将参数 string 数据写入buffer。 offset 偏移量默认值是 0, encoding 编码方式默认是 utf8。 length 长度是将要写入的字符串的 bytes 大小。 返回 number 类型,表示写入了多少 8 位字节流。如果 buffer 没有足够的空间来放整个 string,它将只会只写入部分字符串。 length 默认是 buffer.length - offset。 这个方法不会出现写入部分字符。 |
buf.writeUIntLE(value, offset, byteLength[, noAssert]) | 将 value 写入到 buffer 里, 它由 offset 和 byteLength 决定,最高支持 48 位无符号整数,小端对齐。noAssert 值为 true 时,不再验证 value 和 offset 的有效性。 默认是 false。 |
buf.writeUIntBE(value, offset, byteLength[, noAssert]) | 将 value 写入到 buffer 里, 它由 offset 和 byteLength 决定,最高支持 48 位无符号整数,大端对齐。noAssert 值为 true 时,不再验证 value 和 offset 的有效性。 默认是 false。 |
buf.writeIntLE(value, offset, byteLength[, noAssert]) | 将value 写入到 buffer 里, 它由offset 和 byteLength 决定,最高支持48位有符号整数,小端对齐。noAssert 值为 true 时,不再验证 value 和 offset 的有效性。 默认是 false。 |
buf.writeIntBE(value, offset, byteLength[, noAssert]) | 将value 写入到 buffer 里, 它由offset 和 byteLength 决定,最高支持48位有符号整数,大端对齐。noAssert 值为 true 时,不再验证 value 和 offset 的有效性。 默认是 false。 |
buf.readUIntLE(offset, byteLength[, noAssert]) | 支持读取 48 位以下的无符号数字,小端对齐。noAssert 值为 true 时, offset 不再验证是否超过 buffer 的长度,默认为 false。 |
buf.readUIntBE(offset, byteLength[, noAssert]) | 支持读取 48 位以下的无符号数字,大端对齐。noAssert 值为 true 时, offset 不再验证是否超过 buffer 的长度,默认为 false。 |
buf.readIntLE(offset, byteLength[, noAssert]) | 支持读取 48 位以下的有符号数字,小端对齐。noAssert 值为 true 时, offset 不再验证是否超过 buffer 的长度,默认为 false。 |
buf.readIntBE(offset, byteLength[, noAssert]) | 支持读取 48 位以下的有符号数字,大端对齐。noAssert 值为 true 时, offset 不再验证是否超过 buffer 的长度,默认为 false。 |
buf.toString([encoding[, start[, end]]]) | 根据 encoding 参数(默认是 'utf8')返回一个解码过的 string 类型。还会根据传入的参数 start (默认是 0) 和 end (默认是 buffer.length)作为取值范围。 |
buf.toJSON() | 将 Buffer 实例转换为 JSON 对象。 |
buf[index] | 获取或设置指定的字节。返回值代表一个字节,所以返回值的合法范围是十六进制0x00到0xFF 或者十进制0至 255。 |
buf.equals(otherBuffer) | 比较两个缓冲区是否相等,如果是返回 true,否则返回 false。 |
buf.compare(otherBuffer) | 比较两个 Buffer 对象,返回一个数字,表示 buf 在 otherBuffer 之前,之后或相同。 |
buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]]) | buffer 拷贝,源和目标可以相同。 targetStart 目标开始偏移和 sourceStart 源开始偏移默认都是 0。 sourceEnd 源结束位置偏移默认是源的长度 buffer.length 。 |
buf.slice([start[, end]]) | 剪切 Buffer 对象,根据 start(默认是 0 ) 和 end (默认是 buffer.length ) 偏移和裁剪了索引。 负的索引是从 buffer 尾部开始计算的。 |
buf.readUInt8(offset[, noAssert]) | 根据指定的偏移量,读取一个无符号 8 位整数。若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 如果这样 offset 可能会超出buffer 的末尾。默认是 false。 |
buf.readUInt16LE(offset[, noAssert]) | 根据指定的偏移量,使用特殊的 endian 字节序格式读取一个无符号 16 位整数。若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出 buffer 的末尾。默认是 false。 |
buf.readUInt16BE(offset[, noAssert]) | 根据指定的偏移量,使用特殊的 endian 字节序格式读取一个无符号 16 位整数,大端对齐。若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出 buffer 的末尾。默认是 false。 |
buf.readUInt32LE(offset[, noAssert]) | 根据指定的偏移量,使用指定的 endian 字节序格式读取一个无符号 32 位整数,小端对齐。 若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出buffer 的末尾。默认是 false。 |
buf.readUInt32BE(offset[, noAssert]) | 根据指定的偏移量,使用指定的 endian 字节序格式读取一个无符号 32 位整数,大端对齐。 若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出buffer 的末尾。默认是 false。 |
buf.readInt8(offset[, noAssert]) | 根据指定的偏移量,读取一个有符号 8 位整数。 若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出 buffer 的末尾。默认是 false。 |
buf.readInt16LE(offset[, noAssert]) | 根据指定的偏移量,使用特殊的 endian 格式读取一个 有符号 16 位整数,小端对齐。 若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出 buffer 的末尾。默认是 false。 |
buf.readInt16BE(offset[, noAssert]) | 根据指定的偏移量,使用特殊的 endian 格式读取一个 有符号 16 位整数,大端对齐。 若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出 buffer 的末尾。默认是 false。 |
buf.readInt32LE(offset[, noAssert]) | 根据指定的偏移量,使用指定的 endian 字节序格式读取一个有符号 32 位整数,小端对齐。 若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出buffer 的末尾。默认是 false。 |
buf.readInt32BE(offset[, noAssert]) | 根据指定的偏移量,使用指定的 endian 字节序格式读取一个有符号 32 位整数,大端对齐。 若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出buffer 的末尾。默认是 false。 |
buf.readFloatLE(offset[, noAssert]) | 根据指定的偏移量,使用指定的 endian 字节序格式读取一个 32 位双浮点数,小端对齐。 若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出buffer的末尾。默认是 false。 |
buf.readFloatBE(offset[, noAssert]) | 根据指定的偏移量,使用指定的 endian 字节序格式读取一个 32 位双浮点数,大端对齐。 若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出buffer的末尾。默认是 false。 |
buf.readDoubleLE(offset[, noAssert]) | 根据指定的偏移量,使用指定的 endian字节序格式读取一个 64 位双精度数,小端对齐。 若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出buffer 的末尾。默认是 false。 |
buf.readDoubleBE(offset[, noAssert]) | 根据指定的偏移量,使用指定的 endian字节序格式读取一个 64 位双精度数,大端对齐。 若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 offset 可能会超出buffer 的末尾。默认是 false。 |
buf.writeUInt8(value, offset[, noAssert]) | 根据传入的 offset 偏移量将 value 写入 buffer。注意:value 必须是一个合法的无符号 8 位整数。 若参数 noAssert 为 true 将不会验证 offset 偏移量参数。 这意味着 value 可能过大,或者 offset 可能会超出 buffer 的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则不要使用。默认是 false。 |
buf.writeUInt16LE(value, offset[, noAssert]) | 根据传入的 offset 偏移量和指定的 endian 格式将 value 写入 buffer。注意:value 必须是一个合法的无符号 16 位整数,小端对齐。 若参数 noAssert 为 true 将不会验证 value 和 offset 偏移量参数。 这意味着 value 可能过大,或者 offset 可能会超出buffer的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是 false。 |
buf.writeUInt16BE(value, offset[, noAssert]) | 根据传入的 offset 偏移量和指定的 endian 格式将 value 写入 buffer。注意:value 必须是一个合法的无符号 16 位整数,大端对齐。 若参数 noAssert 为 true 将不会验证 value 和 offset 偏移量参数。 这意味着 value 可能过大,或者 offset 可能会超出buffer的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是 false。 |
buf.writeUInt32LE(value, offset[, noAssert]) | 根据传入的 offset 偏移量和指定的 endian 格式(LITTLE-ENDIAN:小字节序)将 value 写入buffer。注意:value 必须是一个合法的无符号 32 位整数,小端对齐。 若参数 noAssert 为 true 将不会验证 value 和 offset 偏移量参数。 这意味着value 可能过大,或者offset可能会超出buffer的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是 false。 |
buf.writeUInt32BE(value, offset[, noAssert]) | 根据传入的 offset 偏移量和指定的 endian 格式(Big-Endian:大字节序)将 value 写入buffer。注意:value 必须是一个合法的有符号 32 位整数。 若参数 noAssert 为 true 将不会验证 value 和 offset 偏移量参数。 这意味着 value 可能过大,或者offset可能会超出buffer的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是 false。 |
buf.writeInt8(value, offset[, noAssert]) | |
buf.writeInt16LE(value, offset[, noAssert]) | 根据传入的 offset 偏移量和指定的 endian 格式将 value 写入 buffer。注意:value 必须是一个合法的 signed 16 位整数。 若参数 noAssert 为 true 将不会验证 value 和 offset 偏移量参数。 这意味着 value 可能过大,或者 offset 可能会超出 buffer 的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是 false 。 |
buf.writeInt16BE(value, offset[, noAssert]) | 根据传入的 offset 偏移量和指定的 endian 格式将 value 写入 buffer。注意:value 必须是一个合法的 signed 16 位整数。 若参数 noAssert 为 true 将不会验证 value 和 offset 偏移量参数。 这意味着 value 可能过大,或者 offset 可能会超出 buffer 的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是 false 。 |
buf.writeInt32LE(value, offset[, noAssert]) | 根据传入的 offset 偏移量和指定的 endian 格式将 value 写入 buffer。注意:value 必须是一个合法的 signed 32 位整数。 若参数 noAssert 为 true 将不会验证 value 和 offset 偏移量参数。 这意味着 value 可能过大,或者 offset 可能会超出 buffer 的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是 false。 |
buf.writeInt32BE(value, offset[, noAssert]) | 根据传入的 offset 偏移量和指定的 endian 格式将 value 写入 buffer。注意:value 必须是一个合法的 signed 32 位整数。 若参数 noAssert 为 true 将不会验证 value 和 offset 偏移量参数。 这意味着 value 可能过大,或者 offset 可能会超出 buffer 的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是 false。 |
buf.writeFloatLE(value, offset[, noAssert]) | 根据传入的 offset 偏移量和指定的 endian 格式将 value 写入 buffer 。注意:当 value 不是一个 32 位浮点数类型的值时,结果将是不确定的。 若参数 noAssert 为 true 将不会验证 value 和 offset 偏移量参数。 这意味着 value可能过大,或者 offset 可能会超出 buffer 的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是 false。 |
buf.writeFloatBE(value, offset[, noAssert]) | 根据传入的 offset 偏移量和指定的 endian 格式将 value 写入 buffer 。注意:当 value 不是一个 32 位浮点数类型的值时,结果将是不确定的。 若参数 noAssert 为 true 将不会验证 value 和 offset 偏移量参数。 这意味着 value可能过大,或者 offset 可能会超出 buffer 的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是 false。 |
buf.writeDoubleLE(value, offset[, noAssert]) | 根据传入的 offset 偏移量和指定的 endian 格式将 value 写入 buffer。注意:value 必须是一个有效的 64 位double 类型的值。 若参数 noAssert 为 true 将不会验证 value 和 offset 偏移量参数。 这意味着 value 可能过大,或者 offset 可能会超出 buffer 的末尾从而造成value被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是 false。 |
buf.writeDoubleBE(value, offset[, noAssert]) | 根据传入的 offset 偏移量和指定的 endian 格式将 value 写入 buffer。注意:value 必须是一个有效的 64 位double 类型的值。 若参数 noAssert 为 true 将不会验证 value 和 offset 偏移量参数。 这意味着 value 可能过大,或者 offset 可能会超出 buffer 的末尾从而造成value被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用。默认是 false。 |
buf.fill(value[, offset][, end]) | 使用指定的 value 来填充这个 buffer。如果没有指定 offset (默认是 0) 并且 end (默认是 buffer.length) ,将会填充整个buffer。 |
const buf = Buffer.allocUnsafe(6);
buf.writeUIntLE(0x1234567890ab, 0, 6);
// 输出: <Buffer ab 90 78 56 34 12>
console.log(buf);
const buf = Buffer.allocUnsafe(6);
buf.writeUIntBE(0x1234567890ab, 0, 6);
// 输出: <Buffer 12 34 56 78 90 ab>
console.log(buf);
待续。。。。。