@eyhn/msgpack-stream

中文文档
2.8.4发布于 2022/12/01ISCTypeScriptESM + CJS零依赖近 30 天下载 6617

ECMA-262/JavaScript/ TypeScript 信件包

中文使用文档
文档目录30 节
  1. 概要
  2. 目录
  3. 安装
  4. API 密码
  5. encode(data: unknown, options?: EncodeOptions): Uint8Array
  6. decode(buffer: ArrayLike<number> | BufferSource, options?: …
  7. decodeMulti(buffer: ArrayLike<number> | BufferSource, optio…
  8. decodeAsync(stream: ReadableStreamLike<ArrayLike<number> | …
  9. decodeArrayStream(stream: ReadableStreamLike<ArrayLike<numb…
  10. decodeMultiStream(stream: ReadableStreamLike<ArrayLike<numb…
  11. 重用编码器和解码器实例
  12. 扩展类型
  13. 正在解码 Blob
  14. 信件包规格
  15. 信件包映射表
  16. 先决条件
  17. ECMA-262号
  18. 节点JS
  19. 类型脚本编译器/ 类型定义
  20. 基准
  21. 分发
  22. 国家预防机制/npmjs.com
  23. CDN / unpkg.com (中文(简体) )
  24. 德诺支持
  25. 维修
  26. 测试
  27. 持续整合
  28. 单元工程
  29. 更新依赖关系
  30. 许可证

JavaScript/ ECMA- 262 信件包

npm version CI codecov minzip tree-shaking

这是 JavaScript/ECMA-262 执行 邮件包,高效的二进制分泌格式:

https://msgpack.org/ (中文(简体) )

这个库是一个通用的JavaScript,意思是它与所有主要浏览器和NodeJS兼容. 此外,由于执行方式如下: 类型脚本,类型定义文件(d.ts)总是更新并捆绑在分发中.

注意这是JavaScript的MessagePack的第二个版本. 第一个版本在ES5中被执行,从未发布到npmjs.com,被标记为: 经典。 。 。 .

概要

import { deepStrictEqual } from "assert";
import { encode, decode } from "@eyhn/msgpack-stream";

const object = {
  nil: null,
  integer: 1,
  float: Math.PI,
  string: "Hello, world!",
  binary: Uint8Array.from([1, 2, 3]),
  array: [10, 20, 30],
  map: { foo: "bar" },
  timestampExt: new Date(),
};

const encoded: Uint8Array = encode(object);

deepStrictEqual(decode(encoded), object);

目录

安装

此库发布到 npmjs.com 作为 @ eyhn/ msgpack- stream (英语)。 。 。 .

npm install @eyhn/msgpack-stream

API 密码

encode(data: unknown, options?: EncodeOptions): Uint8Array

密码 data 返回一个字节数组为 Uint8Array如果 data 属于或包括一个非连续物体,例如 function 或一个 symbol。 。 。 .

例如:

import { encode } from "@eyhn/msgpack-stream";

const encoded: Uint8Array = encode({ foo: "bar" });
console.log(encoded);

如果你想转换一个 uint8array 到节点JS Buffer,使用时 Buffer.from(arrayBuffer, offset, length) 为了不复制基础 ArrayBuffer时 Buffer.from(uint8array) 复制它:

import { encode } from "@eyhn/msgpack-stream";

const encoded: Uint8Array = encode({ foo: "bar" });

// `buffer` refers the same ArrayBuffer as `encoded`.
const buffer: Buffer = Buffer.from(encoded.buffer, encoded.byteOffset, encoded.byteLength);
console.log(buffer);

EncodeOptions

名称类型默认
扩展代码扩展编码ExtensionCodec.defaultCodec
最大深度编号100
初始缓冲大小编号2048
排序键布尔虚假
部队32布尔虚假
强制整流器布尔虚假
忽略未定义布尔虚假
上下文用户定义- 说吧

decode(buffer: ArrayLike<number> | BufferSource, options?: DecodeOptions): unknown

它解码 buffer 中包含一个已编码信件对象,并返回已解码对象 unknown。 。 。 .

buffer 必须是字节数组, 通常是 Uint8Array 或者说 ArrayBuffer。 。 。 . BufferSource 定义为 ArrayBuffer | ArrayBufferView。 。 。 .

这个 buffer 必须包含单个编码对象。 如果 buffer 包括对象或对象之后的额外字节 buffer 这是空的,它扔 RangeError解码 buffer 包含多个编码对象,使用 decodeMulti() 或者说 decodeMultiStream() (推荐)取而代之.

例如:

import { decode } from "@eyhn/msgpack-stream";

const encoded: Uint8Array;
const object = decode(encoded);
console.log(object);

节点JS Buffer 也可以接受,因为它是 Uint8Array。 。 。 .

DecodeOptions

名称类型默认
扩展代码扩展编码ExtensionCodec.defaultCodec
最大边距编号4_294_967_295 (UINT32 MAX) (英语)
最大边框编号4_294_967_295 (UINT32 MAX) (英语)
最大箭头编号4_294_967_295 (UINT32 MAX) (英语)
最大映射线编号4_294_967_295 (UINT32 MAX) (英语)
最大扩展线编号4_294_967_295 (UINT32 MAX) (英语)
上下文用户定义- 说吧

你用得着 max${Type}Length 以限制每个类型已解码的长度.

decodeMulti(buffer: ArrayLike<number> | BufferSource, options?: DecodeOptions): Generator<unknown, void, unknown>

它解码 buffer ,包括多个MessagePack编码对象,并返回解码对象作为生成器。 另见 decodeMultiStream(),这是此函数的一个同步变体.

此功能不推荐通过 I/O 流解码 MessagePack 二进制, 包括套接字, 因为它是同步的 。 相反, decodeMultiStream() 同步地解码一二进制流,通常花费更少的CPU和内存.

例如:

import { decode } from "@eyhn/msgpack-stream";

const encoded: Uint8Array;

for (const object of decodeMulti(encoded)) {
  console.log(object);
}

decodeAsync(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecodeAsyncOptions): Promise<unknown>

它解码 stream时 ReadableStreamLike<T> 定义为 ReadableStream<T> | AsyncIterable<T>,在字节数组中,返回已解码的对象为 unknown 类型,以 Promise。 。 。 .

此函数同步工作, 并且可能比同步更高效地使用 CPU 资源 decode(),因为它不等待完成下载.

DecodeAsyncOptions 与 DecodeOptions 页:1 decode()。 。 。 .

此功能旨在与 whg 工作 fetch() 像这样:

import { decodeAsync } from "@eyhn/msgpack-stream";

const MSGPACK_TYPE = "application/x-msgpack";

const response = await fetch(url);
const contentType = response.headers.get("Content-Type");
if (contentType && contentType.startsWith(MSGPACK_TYPE) && response.body != null) {
  const object = await decodeAsync(response.body);
  // do something with object
} else { /* handle errors */ }

decodeArrayStream(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecodeAsyncOptions): AsyncIterable<unknown>

一样 decodeAsync(),但仅接受 stream 中包含一系列项目,并逐一发出已解码的项目.

例如:

import { decodeArrayStream } from "@eyhn/msgpack-stream";

const stream: AsyncIterator<Uint8Array>;

// in an async function:
for await (const item of decodeArrayStream(stream)) {
  console.log(item);
}

decodeMultiStream(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecodeAsyncOptions): AsyncIterable<unknown>

一样 decodeAsync() 财务报告和审定财务报表 decodeArrayStream()输入 stream 必须包含多个信息包编码项目。 这是一个同步变体,用于 decodeMulti()。 。 。 .

换句话说,它可以解码无限流并逐一出出解码项目.

例如:

import { decodeMultiStream } from "@eyhn/msgpack-stream";

const stream: AsyncIterator<Uint8Array>;

// in an async function:
for await (const item of decodeMultiStream(stream)) {
  console.log(item);
}

此函数自 v 2. 4. 0 起可用;以前称为 decodeStream()。 。 。 .

重用编码器和解码器实例

Encoder 财务报告和审定财务报表 Decoder 类别通过重用实例来提高性能:

import { deepStrictEqual } from "assert";
import { Encoder, Decoder } from "@eyhn/msgpack-stream";

const encoder = new Encoder();
const decoder = new Decoder();

const encoded: Uint8Array = encoder.encode(object);
deepStrictEqual(decoder.decode(encoded), object);

根据我们的基准 重用 Encoder 例速约20% 比起来 encode() 函数和重用 Decoder 实例速度约2% 比起来 decode() 函数。 注意其结果应因环境而异 和数据结构.

扩展类型

处理 信件包扩展类型,该图书馆提供 ExtensionCodec 课.

这是设置自定义扩展类型处理的示例 Map 财务报告和审定财务报表 Set 类型脚本中的类 :

import { encode, decode, ExtensionCodec } from "@eyhn/msgpack-stream";

const extensionCodec = new ExtensionCodec();

// Set<T>
const SET_EXT_TYPE = 0 // Any in 0-127
extensionCodec.register({
  type: SET_EXT_TYPE,
  encode: (object: unknown): Uint8Array | null => {
    if (object instanceof Set) {
      return encode([...object]);
    } else {
      return null;
    }
  },
  decode: (data: Uint8Array) => {
    const array = decode(data) as Array<unknown>;
    return new Set(array);
  },
});

// Map<T>
const MAP_EXT_TYPE = 1; // Any in 0-127
extensionCodec.register({
  type: MAP_EXT_TYPE,
  encode: (object: unknown): Uint8Array => {
    if (object instanceof Map) {
      return encode([...object]);
    } else {
      return null;
    }
  },
  decode: (data: Uint8Array) => {
    const array = decode(data) as Array<[unknown, unknown]>;
    return new Map(array);
  },
});

const encoded = encode([new Set<any>(), new Map<any, any>()], { extensionCodec });
const decoded = decode(encoded, { extensionCodec });

不是自定义对象的扩展类型必须是 [0, 127]时 [-1, -128] 保留给 MessagePack 本身.

扩展Codec 上下文

当您使用扩展编码器时,可能需要有编码/解码状态来跟踪哪些对象被编码/再创建. 要做到这一点,通过一个 context 页:1 EncodeOptions 财务报告和审定财务报表 DecodeOptions数字 :

import { encode, decode, ExtensionCodec } from "@eyhn/msgpack-stream";

class MyContext {
  track(object: any) { /*...*/ }
}

class MyType { /* ... */ }

const extensionCodec = new ExtensionCodec<MyContext>();

// MyType
const MYTYPE_EXT_TYPE = 0 // Any in 0-127
extensionCodec.register({
  type: MYTYPE_EXT_TYPE,
  encode: (object, context) => {
    if (object instanceof MyType) {
      context.track(object); // <-- like this
      return encode(object.toJSON(), { extensionCodec, context });
    } else {
      return null;
    }
  },
  decode: (data, extType, context) => {
    const decoded = decode(data, { extensionCodec, context });
    const my = new MyType(decoded);
    context.track(my); // <-- and like this
    return my;
  },
});

// and later
import { encode, decode } from "@eyhn/msgpack-stream";

const context = new MyContext();

const encoded = = encode({myType: new MyType<any>()}, { extensionCodec, context });
const decoded = decode(encoded, { extensionCodec, context });

处理扩展大小

此库不默认处理 BigInt, 但您可以用 ExtensionCodec 像这样:

import { deepStrictEqual } from "assert";
import { encode, decode, ExtensionCodec } from "@eyhn/msgpack-stream";

const BIGINT_EXT_TYPE = 0; // Any in 0-127
const extensionCodec = new ExtensionCodec();
extensionCodec.register({
    type: BIGINT_EXT_TYPE,
    encode: (input: unknown) => {
        if (typeof input === "bigint") {
            if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) {
                return encode(parseInt(input.toString(), 10));
            } else {
                return encode(input.toString());
            }
        } else {
            return null;
        }
    },
    decode: (data: Uint8Array) => {
        return BigInt(decode(data));
    },
});

const value = BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1);
const encoded: = encode(value, { extensionCodec });
deepStrictEqual(decode(encoded, { extensionCodec }), value);

时间模块作为时间戳扩展

有人提议在JavaScript中提出新的日期/时间说明:

这个图书馆地图 Date 切换到 MessagePack 时间戳扩展,但您可以重新绘制时间模块(或 时间多填充像这样的时间戳扩展:

import { Instant } from "@std-proposal/temporal";
import { deepStrictEqual } from "assert";
import {
  encode,
  decode,
  ExtensionCodec,
  EXT_TIMESTAMP,
  encodeTimeSpecToTimestamp,
  decodeTimestampToTimeSpec,
} from "@eyhn/msgpack-stream";

const extensionCodec = new ExtensionCodec();
extensionCodec.register({
  type: EXT_TIMESTAMP, // override the default behavior!
  encode: (input: any) => {
    if (input instanceof Instant) {
      const sec = input.seconds;
      const nsec = Number(input.nanoseconds - BigInt(sec) * BigInt(1e9));
      return encodeTimeSpecToTimestamp({ sec, nsec });
    } else {
      return null;
    }
  },
  decode: (data: Uint8Array) => {
    const timeSpec = decodeTimestampToTimeSpec(data);
    const sec = BigInt(timeSpec.sec);
    const nsec = BigInt(timeSpec.nsec);
    return Instant.fromEpochNanoseconds(sec * BigInt(1e9) + nsec);
  },
});

const instant = Instant.fromEpochMilliseconds(Date.now());
const encoded = encode(instant, { extensionCodec });
const decoded = decode(encoded, { extensionCodec });
deepStrictEqual(decoded, instant);

如果时间模块实现标准化,这将成为本库中带有主要版本递增的默认.

正在解码 Blob

Blob 是浏览器提供的二进制数据容器。 要读取其内容, 您可以使用 Blob#arrayBuffer() 或者说 Blob#stream()。 。 。 . Blob#stream() 如果目标平台支持,则推荐。 这是因为流出 对大型物体来说,解码速度应该更快。 两种方式,你都需要使用 一个同步 API.

async function decodeFromBlob(blob: Blob): unknown {
  if (blob.stream) {
    // Blob#stream(): ReadableStream<Uint8Array> (recommended)
    return await decodeAsync(blob.stream());
  } else {
    // Blob#arrayBuffer(): Promise<ArrayBuffer> (if stream() is not available)
    return decode(await blob.arrayBuffer());
  }
}

信件包规格

本库与MessagePack规格的"2017年8月"修订版相兼容,此时已添加了时间戳分机:

  • str/bin 离职,2013年8月增加
  • 扩展类型,2013年8月增加
  • 时间戳分机类型,2017年8月添加

生活规格如下:

https://github.com/msgpack/msgpack 页面存档备份,存于互联网档案馆

请注意,截至2019年6月,MessagePack规格上没有正式"版本". 见 https://github.com/msgpack/msgpack/issues/195 互联网档案馆的存檔,存档日期2011-12-02 讨论.

信件包映射表

下表显示 JavaScript 值的映射方式 信件包格式 而反之亦然.

源值信件包格式数值已解码
无效, 未定义无无效(*1)
布尔( 真, 假)布尔家族布尔( 真, 假)
数字( 53- 位英寸)输入家庭数字( 53- 位英寸)
数字( 64- 位浮点)浮动家族数字( 64- 位浮点)
字符串家庭关系字符串
线条缓冲维尤宾家Uint8 箭头 (*2)
阵列数组家族阵列
对象地图家族对象(*3)
日期时间戳分机家族日期(*4)
  • *1 两者兼有 null 财务报告和审定财务报表 undefined 被映射到 nil (单位:千美元)0xC0)类型,并被解码为 null
  • *2 任意 ArrayBufferView包括节点JS Buffer 被映射到 bin 并解码为 Uint8Array
  • *3 处理 Object,它被视为 Record<string, unknown> 在类型脚本方面
  • *4 MessagePack时间戳可能有纳秒,解码为JavaScript后会丢失 Date。可以通过注册来推翻这种行为 -1 用于扩展编码器.

先决条件

这是一个通用的JavaScript库,支持主要浏览器和节点JS.

ECMA-262号

  • ES5语言特性
  • ES2018标准库,包括:
    • 已键入数组( ES2015)
    • 合成(ES2018)
    • ES2015-ES2018中添加的地物

本库使用的标准 ES2018 库可以多填充 核心 js 数据。 。 。 .

如果支持 IE11,则导入 core-js 在应用程序条目点中,如同此库在测试浏览器时所做的那样.

节点JS

需要NodeJS v10,但NodeJS v12或后期推荐,因为它包括了V8的特性 改进V8中的数据视频性能。 。 。 .

V10 前的节点JS 将通过导入工作 @eyhn/msgpack-stream/dist.es2015+umd/msgpack。 。 。 .

类型脚本编译器/ 类型定义

本单元需要类型定义 AsyncIterator, (中文(简体) ), SourceBuffer,Whatwg溪流,等等。 由下列机构提供: "lib": ["ES2021", "DOM"] 内 tsconfig.json。 。 。 .

关于TypeScript编译器版本,只在开发中测试最新的TypeScript.

基准

运行时间性能并不是使用MessagePack的唯一原因,重要的是选择MessagePack库,因此提供了一套基准套件来监控这个库的性能.

V8的内置JSON多年得到改进,esp. JSON.parse() 实值 v8/7.6号文件显著改进如基准结果bellow所示,它是截至2019年最快的去序列器.

然而,MessagePack可以有效处理二进制数据,实际性能取决于情况. 如果表现很重要,你最好用自己的用法做基准.

节点JS/v18.1.0的基准(V8/10.1)

操作执行分钟行动
buf = 从(JSON.stringify(obj));902100 (英语)5000块180420 (英语)
obj = JSON.parse(buf.toString ("utf-8"));898700 (英语)5000块179740 (英语)
buf = 需要 ("msgpack-lite"). encode(obj;);411000 (411000) (中文(简体) )5000块82200 (英语)
obj = 要求 ("msgpack-lite").decode (buf;);246200 (英语)5001 (简体中文)49230 (英语)
buf = 要求 (""@eyhn/msgpack-stream"). encode(obj;);843300 (英语)5000块168660 (英语)
obj = 需要 (""@eyhn/msgpack-stream").decode(buf; );489300 (英语)5000块97860 (英语)
buf=/ *@eyhn/msgpack-stream */编码器.encode(obj);第1154200号5000块230840 (英语)
obj = / * @eyhn/msgpack-stream */decoder.decode(buf) ; (中文(简体) );448900 (英语)5000块89780 (英语)

请注意: JSON 案件使用情况 Buffer 用于模拟 JavaScript 字符串必须被转换成UTF-8编码的字节数组的 I/O, 而MessagePack 模块处理字节数组.

分发

国家预防机制/npmjs.com

以npmjs.com分发的国家预防机制包包括ES2015+和ES2015文件:

  • dist/ 由CommomJS编译为ES2019,为NodeJS v10提供
  • dist.es2015+umd/ 与UMD编译为ES2015
    • dist.es2015+umd/msgpack.min.js - 已修改的文件
    • dist.es2015+umd/msgpack.js - 未缩小的文件
  • dist.es2015+esm/ 汇编成ES2015,并配有ES模块,为类似网络包装的捆绑器和NodeJS的无害环境管理模式提供

如果使用NodeJS和/或webpack,他们的模块解析器会自动使用合适的.

CDN / unpkg.com (中文(简体) )

此库可通过 CDN 访问 :

<script crossorigin src="https://unpkg.com/@eyhn/msgpack-stream"></script>

装入 MessagePack 模块.

德诺支持

你可以在德诺使用这个模块.

见 example/deno-*.ts 用于实例.

deno.land/x 尚未支持.

维修

测试

简单的测试:

npm run test

持续整合

这个图书馆使用Travis CI.

测试矩阵 :

  • 类型脚本目标
    • target=es2019 编号 : target=es5
  • JavaScript 引擎
    • 节点JS,浏览器(Chrome,Firefox,Safari,IE11等)

见 测试:* 在包件.json中 财务报告和审定财务报表 .travis.yml (英语) 详细情况.

单元工程

# run tests on NodeJS, Chrome, and Firefox
make test-all

# edit the changelog
code CHANGELOG.md

# bump version
npm version patch|minor|major

# run the publishing task
make publish

更新依赖关系

npm run update-dependencies

许可证

版权2019 腾讯网.

本软件使用ISC许可证:

https://opensource.org/licenses/ISC 页面存档备份,存于互联网档案馆

见 自由主义 详细情况.

版本与发布记录

@eyhn/msgpack-stream 共发布 5 个版本,首次发布于 2022/11/24;过去 12 个月发布了 0 个版本。

版本发布日期距今
2.8.4latest2022/12/013 年前
2.8.32022/12/013 年前
2.8.22022/11/303 年前
2.8.12022/11/303 年前
2.8.02022/11/243 年前

关于 @eyhn/msgpack-stream 的常见问题

@eyhn/msgpack-stream 是什么?

ECMA-262/JavaScript/ TypeScript 信件包

如何安装 @eyhn/msgpack-stream?

在项目目录运行 npm install @eyhn/msgpack-stream,或使用 pnpm add / yarn add / bun add。

@eyhn/msgpack-stream 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@eyhn/msgpack-stream 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@eyhn/msgpack-stream 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >= 10。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@eyhn/msgpack-stream 可以商用吗?

@eyhn/msgpack-stream 使用 ISC 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@eyhn/msgpack-stream 的下载量有多少?

根据 npm 官方下载统计,@eyhn/msgpack-stream 在 2026/10/14 – 2026/11/12 这 30 天内被下载 6,617 次,日均约 221 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@eyhn/msgpack-stream 还在维护吗?

最新版本 2.8.4 发布于 2022/12/01(3 年前);至今共发布 5 个版本,其中过去 12 个月发布了 0 个;首次发布于 2022/11/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。