再见Node.js缓冲区,是时候从 Buffer 转移到 Uint8Array 了

摘要:从一开始,该Buffer类型就一直是 Node.js 中二进制数据处理的基石。然而,现在我们有了Uint8Array,它是一种原生 JavaScript 类型并且可以跨平台工作。虽然Buffer是 的一个实例Uint8Array

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

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

是时候继续前进了。


计划

我打算将所有包从Bufferusing移至Uint8Array. 如果您是 JavaScript 包的维护者,我鼓励您也这样做。

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


如何

首先,熟悉和之间微妙的不兼容性。Uint8ArrayBuffer

我制作了这个uint8array-extras包以使过渡更容易。欢迎请求其他实用程序。

如果您的代码接受 aBuffer并且不使用任何Buffer特定于 的方法,您只需将文档和类型更新为Uint8Array. 将输入类型从Bufferto更改Uint8Array为非破坏性更改,因为Buffer是 的实例Uint8Array。

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

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

主要过渡步骤是:

  • 删除所有import {Buffer} from 'node:buffer'导入。
  • 删除所有出现的Buffer全局。
  • 停止使用Buffer特定方法。
  • 替换Buffer读/写方法。


问题

Buffer最初为什么存在?

Buffer早在Uint8Array存在之前就被创建了。

如何使用 Base64 进行转换Uint8Array?

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

如何处理返回 a 的 Node.js API Buffer(如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 APIUint8Array也接受,因此不需要额外的工作。理想情况下,此代码还应转换为Web Crypto,但这与本示例无关。

TypeScript

-import {Buffer} from 'node:buffer';

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


执行

我建议强制执行Uint8Arraylinting 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,它很快就会默认带有此配置。

翻译来自:https://sindresorhus.com/blog/goodbye-nodejs-buffer

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://shenqiku.cn/article/FLY_12548