本文不是原文翻译
英文原文地址:JavaScript's New Superpower: Explicit Resource Management
提案地址: https://github.com/tc39/proposal-explicit-resource-management
这是一个实验性语法提案
目前该提案处于 pending stage 4
阶段
从 Chromium v134
和 V8 的 v13.8
开始提供支持。
该提案的作用
通过一种显示方法来管理资源的生命周期,这里的资源包括:内存、I/O、文件操作(file handles)、网络连接等
提案引入的内容
- using 和 await using
- DisposableStack 和 AsyncDisposableStack
using / await using
用法:
using x = xxx;
await using x = xxx;
使用 using
或 await using
声明的变量,会在函数体、块或者模块结尾被处理,即作用域结束时自动触发 dispose 方法 ,
要自动触发 dispose / asyncDispose 方法的前提是要自己实现 dispose / asyncDispose 方法
提案之前的代码 VS 提案之后的代码
基础代码:
// 同步资源
class SyncResource {
constructor(name) {
this.name = name;
console.log(`打开资源: ${name}`);
}
use() {
console.log(`使用资源: ${this.name}`);
}
[Symbol.dispose]() {
console.log(`释放资源: ${this.name}`);
}
}
// 异步资源
class AsyncResource {
constructor(name) {
this.name = name;
}
static async open(name) {
console.log(`异步打开资源: ${name}`);
await new Promise(r => setTimeout(r, 100));
return new AsyncResource(name);
}
async use() {
console.log(`异步使用资源: ${this.name}`);
}
async [Symbol.asyncDispose]() {
console.log(`异步释放资源: ${this.name}`);
await new Promise(r => setTimeout(r, 100));
}
}
新提案之前
function withoutUsing() {
const res = new SyncResource("Logger");
try {
res.use();
} finally {
res[Symbol.dispose]();
}
}
async function withoutAwaitUsing() {
const res = await AsyncResource.open("DB");
try {
await res.use();
} finally {
await res[Symbol.asyncDispose]();
}
}
提案之后
function withUsing() {
using res = new SyncResource("Logger");
res.use();
}
// 自动调用 res[Symbol.dispose](),即使出错也能释放
在作用域结束时自动释放资源,避免了忘记手动释放
DisposableStack / AsyncDisposableStack
- 用于手动管理多个资源的释放顺序;
- 遵循栈结构,注册的资源后进先出(LIFO);
- 这两个对象提供一系列方法,比如
use()
、adopt()
、defer()
等
使用示例:
function exampleUsingStack() {
const stack = new DisposableStack();
const file = {
name: "log.txt",
[Symbol.dispose]() {
console.log(`关闭文件 ${this.name}`);
}
};
const db = {
name: "local.db",
[Symbol.dispose]() {
console.log(`关闭数据库 ${this.name}`);
}
};
stack.use(file); // 注册 file 的释放
stack.use(db); // 注册 db 的释放
stack.dispose(); // 自动依序调用 db → file 的释放逻辑
}
exampleUsingStack()
async function exampleAsyncStack() {
const stack = new AsyncDisposableStack();
const conn = {
name: "async-db",
async [Symbol.asyncDispose]() {
console.log(`关闭异步连接 ${this.name}`);
}
};
const tmpFile = {
name: "temp.txt",
async [Symbol.asyncDispose]() {
console.log(`删除临时文件 ${this.name}`);
}
};
stack.use(conn);
stack.use(tmpFile);
await stack.dispose(); // 顺序释放资源(tmpFile → conn)
}
await exampleAsyncStack();
完
感谢你的阅读