Javascript的新能力:显式资源管理(Explicit Resource Management)
本文首发在我的个人博客上:Javascript的新能力:显式资源管理(Explicit Resource Management)
https://www.brandhuang.com/article/1749888651434
本文不是原文翻译
英文原文地址: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();
完
感谢你的阅读