【译】再见,Node.js 缓冲区

再见,Node.js 缓冲区

从一开始,Buffer 类型就一直是 Node.js 中二进制数据处理的基石。 然而,现在我们有了 Uint8Array,它是一种原生 JavaScript 类型,可以跨平台工作 。 虽然“Buffer”是“Uint8Array”的一个实例,但它引入了许多在其他 JavaScript 环境中不可用的方法。 因此,利用特定于 Buffer 的方法的代码需要进行多填充,从而阻止许多有价值的包与浏览器兼容。

“Buffer”还带有额外的警告。 例如, Buffer#slice() 创建一个链接到原始 Buffer 的可变段,而 Uint8Array#slice( ) 创建一个不可变的副本,从而可能导致不可预测的行为。 问题不在于 Buffer#slice() 方法的行为,而在于 Buffer 是 Uint8Array 的子类,并且完全改变了继承方法的行为。 使用“Uint8Array#subarray()”或“Buffer#subarray()”代替“Buffer#slice()”。 此外,缓冲区通过全局变量暴露私人信息,存在潜在的安全风险。

是时候继续前进了。

## 计划

我打算将我的所有包从使用Buffer移动到Uint8Array。 如果您是 JavaScript 包的维护者,我鼓励您也这样做。

“Buffer”永远不会被删除,甚至可能永远不会被弃用,但至少社区可以慢慢摆脱它。 我希望 Node.js 团队至少开始阻止使用“Buffer”。

## 如何

首先,熟悉“Uint8Array”和“Buffer”之间的微妙的不兼容性

我制作了 uint8array-extras 以使转换更容易。 欢迎请求其他实用程序。

如果您的代码接受“Buffer”并且不使用任何“Buffer”特定的方法,您只需将文档和类型更新为“Uint8Array”即可。 将输入类型从“Buffer”更改为“Uint8Array”是一项非重大更改,因为“Buffer”是“Uint8Array”的实例。

将返回类型从“Buffer”更改为“Uint8Array”是一项重大更改,因为消费者可能会使用“Buffer”特定的方法。

如果您绝对需要将 Uint8Array 转换为 Buffer,您可以使用 Buffer.from(uint8Array) (复制数据)或 Buffer.from(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength) (不复制)。 然而,通常有更好的方法。

主要过渡步骤是:

  • 删除所有 import {Buffer} from 'node:buffer' 导入。
  • 删除所有出现的“Buffer”全局变量。
  • 停止使用特定于“Buffer”的方法。
  • Buffer 读/写方法替换为 [DataView](https://developer .mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView)。

### 问题

为什么要存在“Buffer”?

“Buffer”是在“Uint8Array”存在之前很久就创建的。

如何使用 Uint8Array 与 Base64 相互转换?

您现在可以使用我的uint8array-extras。 它很可能最终会在 JavaScript 中得到原生支持

如何处理返回 Buffer 的 Node.js API,例如 fs 方法?

由于“Buffer”是“Uint8Array”的子类,因此您可以将其视为“Uint8Array”。 只需确保您不使用“.slice()”(其行为不同)或任何特定于缓冲区的方法。

### 例子

JavaScript
import {stringToBase64} from 'uint8array-extras';

Buffer.from(string).toString('base64');
stringToBase64(string);
import {uint8ArrayToHex} from 'uint8array-extras';

buffer.toString('hex');
uint8ArrayToHex(uint8Array);
 const bytes = getBytes();

const view = new DataView(bytes.buffer);

const value = bytes.readInt32BE(1);
const value = view.getInt32(1);
 import crypto from 'node:crypto';
import {Buffer} from 'node:buffer';
import {isUint8Array} from 'uint8array-extras';

 export default function hash(data) {
	if (!(typeof data === 'string' || Buffer.isBuffer(data))) {
	if (!(typeof data === 'string' || isUint8Array(data))) {
 		throw new TypeError('Incorrect type.');
 	}

 	return crypto.createHash('md5').update(data).digest('hex');
 }

大多数 Node.js API 也接受 Uint8Array,因此不需要额外的工作。 理想情况下,此代码还应转换为 Web Crypto,但这与本示例无关。

打字稿
import {Buffer} from 'node:buffer';

export function getSize(input: string | Buffer): number { … }
export function getSize(input: string | Uint8Array): number { … }

执行

我建议通过 linting 强制使用“Uint8Array”而不是“Buffer”。

将其添加到您的 ESLint 配置中:

{
	'no-restricted-globals': [
		'error',
		{
			name: 'Buffer',
			message: 'Use Uint8Array instead.'
		}
	],
	'no-restricted-imports': [
		'error',
		{
			name: 'buffer',
			message: 'Use Uint8Array instead.'
		},
		{
			name: 'node:buffer',
			message: 'Use Uint8Array instead.'
		}
	]
}

如果您使用 TypeScript,请添加以下内容:

{
	'@typescript-eslint/ban-types': [
		'error',
		{
			types: {
				Buffer: {
					message: 'Use Uint8Array instead.',
					suggest: [
						'Uint8Array'
					]
				}
			}
		}
	]
}

如果您使用XO,它很快就会默认带有此配置。

我可以帮忙吗?

表达你的支持 对于使用 Uint8Array 的 Node.js 新 API。

帮我将我的包移动到Uint8Array。 选择一个并尝试一下。

帮助我们制定一个 lint 规则 以防止使用 Buffer 方法。

## 未来

Uint8Array(或者更确切地说,TypedArray)需要更多实用方法!

例如,目前没有好的内置方法可以将 Uint8Array 转换为 Base64 或 Hex。 尽管如此,看起来这很可能会出现

考虑向 TC39 提出缺失的位。

## 结束

让我们让 JavaScript 包生态系统更加跨平台。 谢谢阅读。

讨论

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值