js中的using声明

一、using 声明简介

usingECMAScript 2023(ES14) 引入的一项新语法,用于自动管理资源的生命周期

它的主要目标是简化"资源使用完后自动释放"的场景,例如文件句柄、数据库连接、锁等。 相关提案可见:github.com/tc39/propos...

📜 语法结构:

csharp 复制代码
using 变量名 = 表达式;
await using 变量名 = 异步表达式;

using 声明的变量必须是一个实现了 Symbol.disposeSymbol.asyncDispose 方法的对象。

当作用域退出(无论是正常返回还是异常)时,JS 引擎会自动调用该方法释放资源。


二、基本使用示例

同步版本

javascript 复制代码
class File {
  constructor(name) {
    this.name = name;
    console.log(`打开文件: ${name}`);
  }
  [Symbol.dispose]() {
    console.log(`关闭文件: ${this.name}`);
  }
}

function main() {
  using f = new File("data.txt");
  console.log("读取文件中...");
}

main();
// 输出:
// 打开文件: data.txt
// 读取文件中...
// 关闭文件: data.txt

⚡ 当 main() 执行完毕时,f 离开作用域,系统会自动调用 f[Symbol.dispose]()


异步版本

javascript 复制代码
class AsyncResource {
  async [Symbol.asyncDispose]() {
    console.log("异步释放资源...");
    await new Promise(res => setTimeout(res, 1000));
    console.log("资源已释放");
  }
}

async function run() {
  await using r = new AsyncResource();
  console.log("使用异步资源中...");
}

run();

三、内部机制简析

  • using词法作用域绑定 (和 let/const 类似)。

  • 离开作用域时:

    • 如果是同步资源 → 调用 [Symbol.dispose]()
    • 如果是异步资源 → 调用 [Symbol.asyncDispose]()
  • 它可以和 trycatchfinally 一起安全使用。


四、使用场景

场景 传统做法 新写法(using)
文件操作 try/finally 手动关闭 自动调用 dispose
数据库连接 手动断开 自动释放连接
临时锁 try/finally 释放锁 离开作用域自动释放

五、注意事项

  1. using 只能在模块或函数作用域中使用,不能在全局作用域直接声明。
  2. 不能与 var 共用。
  3. 不会影响 GC(垃圾回收),它只是提供结构化释放资源的机制。

六、实践demo------简化revokeObjectURL

在图片回显/文件下载等场景中,开发很容易忘记revokeObjectURL,我们可以利用using特性进行封装,消除revokeObjectURL的心智负担。

就比如上传图片后回显的操作:

js 复制代码
console.log('🚀 using demo 启动...');

function objectURLResource(blob) {
    const url = URL.createObjectURL(blob);
    console.log('🆕 创建 URL:', url);
    return {
        url,
          [Symbol.dispose]() {
            console.log("释放资源...");
            URL.revokeObjectURL(url);
            console.log('🧹 自动释放 URL:', url);
            
        },
        // [Symbol.dispose]() {
        //     console.log("释放资源...");
        //     new Promise(resolve => setTimeout(resolve, 1000)).then(()=>{
        //         URL.revokeObjectURL(url);
        //         console.log('🧹 自动释放 URL:', url);
        //     })
            
        // },
          async [Symbol.asyncDispose]() {
            console.log("异步释放资源...");
            await new Promise(resolve => setTimeout(resolve, 3000)); // 模拟异步操作
            URL.revokeObjectURL(url);
            console.log('🧹 自动释放 URL:', url);
        },
    };
}



async function showImage(blob) {
    // await using resource = objectURLResource(blob);
    using resource = objectURLResource(blob);
    const img = document.createElement('img');
    img.src = resource.url;
    img.alt = 'demo';
    const { resolve, promise } = Promise.withResolvers()
    img.onload = () => {
        resolve()
    }
    document.body.appendChild(img);
    await promise;
    console.log('✅ 演示完毕,URL 将被自动 revoke');
}
document.querySelector('#file').addEventListener('change',async (e) => {
    const f = e.target.files[0]
   await showImage(f);
   console.log('do others...    ')

})

revokeObjectURL的注意事项

当img加载后,执行revokeObjectURL并不会影响内容显示,但如果img未加载完就执行了revokeObjectURL,则无法显示图片。因此以上demo中增加了await promise的处理,确保图片被显示出来。

那么可能会有人问,此处能否用Symbol.asyncDispose来解决该问题?答案是不能。但这是一个很好的问题,触及到了 Symbol.asyncDisposeSymbol.dispose的根本区别.

七、Symbol.asyncDispose与Symbol.dispose的区别

表面上看,以上demo中如果写成await using resource = objectURLResource(blob);,释放资源用的是Symbol.asyncDispose,如果不加await,则调用Symbol.dispose

异步释放:

那么这两个api的使用场景分别是啥呢?我们不妨在同步释放中写下如下代码:

javascript 复制代码
[Symbol.dispose]() {
    console.log("释放资源...");
    new Promise(resolve => setTimeout(resolve, 1000)).then(()=>{
        URL.revokeObjectURL(url);
        console.log('🧹 自动释放 URL:', url);
    })
},

可以看到,do others...在释放完成前就执行了。

因此可以理解:Symbol.asyncDispose是为了让后续的代码等待异步释放完成后再执行,因为有些释放场景,可能需要进行io或其他异步校验,而Symbol.dispose释放过程是同步的,后续代码执行时可以认为资源已经被释放了。如果后续代码执行时并不关心该资源是否已经释放了,那使用Symbol.dispose即可。

相关推荐
一叶飘零晋2 分钟前
【(一)Electron 使用之如何用vite+vue3搭建初始框架】
前端·javascript·electron
光影少年14 分钟前
前端SSR和ssg区别
前端·vue.js·人工智能·学习·react.js
广州华水科技18 分钟前
北斗形变监测传感器在水库安全监测中的应用与发展
前端
凯瑟琳.奥古斯特1 小时前
Bootstrap快速上手指南
开发语言·前端·css·bootstrap·html
精益数智工坊1 小时前
拆解制造业仓库物料管理流程:如何通过标准化仓库物料管理流程解决账实不符难题
大数据·前端·数据库·人工智能·精益工程
恶猫1 小时前
网页自动化模拟操作时,模拟真实按键触发事件【终级方案】
前端·javascript·自动化·vue·网页模拟
小羊Yveesss1 小时前
2026年前端开发新趋势:智能协同、工具革新与场景深耕
前端·ai
Dxy12393102161 小时前
HTML中的Canvas可以干哪些事情
前端·html
悟乙己1 小时前
解析 Agent 时代的 HTML PPT SKILLS: html-ppt-skill
前端·html·powerpoint
ZC跨境爬虫2 小时前
跟着 MDN 学 HTML day_2:(表单分组与高级输入控件实战)
前端·javascript·css·ui·html