前言

TypeScript v5.2 多了一个新功能叫 Disposable。

Dispose 的作用是让 "对象" 离开 "作用域" 后做出一些 "释放资源" 的操作。

很多地方都可以看到 Dispose 概念。比如 Web Component 的 disconnectedCallback,Angular 组件的 ngOnDestroy

而对象释放资源在其它面向对象语言中也很常见,比如 C# 的 Dispose Pattern

所以这一次 TypeScript 只是推出了一个本来就该有的功能而已。

之所以这么迟才推出,是因为这个功能可以用其它方式替代(虽然不够优雅),而且 Dispose 在后端比较需要,前端现在都迷函数式,对象反而越来越少见了。

参考

YouTube – NEW Way To Create Variables In JavaScript

Docs – Announcing TypeScript 5.2

TypeScript 5.2's New Keyword: 'using'

目前的支持度

Disposable 并不是 TypeSCript 语法,而是 JavaScript ECMA 标准。目前在 stage 3

当然 TypeScript 会做 down-level 处理,target ES2017 也可以使用,只是需要添加两句 runtime polyfill 就可以了。

在我写着一篇时,PrettierESLintesbuild 都还不支持 Disposable。要测试只能用 TypeScript Compiler (AKA tsc)。

Prettier Issue, esbuild issue 视乎还没人去提。

搭建环境

用 tsc 搭建环境,不会的可以看这篇

在 tsconfig.json 加入 compilerOptions.lib "ESNext.Disposable"

{
"compilerOptions": {
"target": "ES2017",
"lib": ["ES2017", "ESNext.Disposable", "DOM"]
}
}

我测试时完整的 tsconfig.json 如下

{
"compilerOptions": {
"target": "es2017",
"lib": [
"DOM",
"DOM.Iterable",
"ES2017",
"ES2019.Array",
"ES2019.Object",
"ESNext.Disposable"
],
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"useDefineForClassFields": true,
"noImplicitOverride": true,
"exactOptionalPropertyTypes": true,
"forceConsistentCasingInFileNames": true,
/* Others */
"skipLibCheck": true,
"sourceMap": true,
}
}

然后加上 runtime polyfill

(Symbol as { dispose: symbol }).dispose ??= Symbol("Symbol.dispose");
(Symbol as { asyncDispose: symbol }).asyncDispose ??= Symbol("Symbol.asyncDispose");

注: 我这里只是做了一个轻量版,严格来说需要添加更多的 polyfill 的。

详情参考这篇:

没有 Disposable 怎么释放资源?

首先有个对象

class Person {
private intervalNumber: number;
constructor() {
this.intervalNumber = setInterval(() => console.log('call'), 1000);
}
dispose() {
clearInterval(this.intervalNumber);
}
}

对象用到了一个全局资源  setInterval,并曝露了一个接口释放该资源。

使用的情况下是这样的。

document.addEventListener('click', () => {
const person = new Person();
// do something...
person.dispose();
});

这样写不够安全,因为如果 do something 不小心报错,就会导致 dispose 没有被执行。于是

document.addEventListener('click', () => {
const person = new Person();
try {
// do something...
} catch {
console.log('error');
} finally {
person.dispose();
}
});

繁琐了很多,但是还可以接受,毕竟需要错误处理嘛。但是...如果我们不需要错误处理呢?

document.addEventListener('click', () => {
const person = new Person();
// do something...
if (Math.random() > 0.5) return;
person.dispose();
});

即便没有错误,只是 return 也会导致 dispose 没有执行。这个时候硬硬加 try finally 就有点过分了。

所以我们需要 Disposable 来优化,让代码变得优雅。

有 Disposable 怎样释放资源?

首先修改我们的 Person class。

class Person implements Disposable {
private intervalNumber: number; constructor() {
this.intervalNumber = setInterval(() => console.log('call'), 1000);
} [Symbol.dispose] {
clearInterval(this.intervalNumber);
}
}

原本的 dispose 方法变成了 [Symbol.dispose] 方法。还有 class 多了一个 implements Disposable

对象属性名配 Symbol 这个 pattern 是 JavaScript 一路以来的玩法。Iterator 也是这个玩法。

使用的情况下是这样的。

document.addEventListener("click", () => {
using person = new Person();
// do something...
if (Math.random() > 0.5) return;
});

person 前面把 const 改成了新的语法 "using"。然后...就没有然后了。

我们甚至都不需要调用 dispose。它自己会调用。

dispose 被调用的时机

using 在哪一个作用域,当那个作用域完结的时候,dispose 就会被调用。

上面例子中,我刻意加了一个花括弧作为 using 的 scope。所以触发的顺序是 1, 2, 3。

注意: JS 管理作用域的写法和 C# 不同哦。

下面是依据 C# 的写法。结果和上面的顺序是不相同的哦。不要搞错哦。

asyncDispose

如果释放资源是一个异步过程,那需要使用 asyncDispose

下面几个地方换成 async 就可以了。

然后调用时也加上 async 就可以了。

Downlevel Emit

参考: Github – Support using and await using declarations

using 会被 transpile 成 try finally。所以即使我们 target ES2017 也是可以使用 Displosable 功能的哦。

TypeScript – Using Disposable的更多相关文章

  1. 使用TypeScript拓展你自己的VS Code!

    0x00 前言 在前几天的美国纽约,微软举行了Connect(); //2015大会.通过这次大会,我们可以很高兴的看到微软的确变得更加开放也更加务实了.当然,会上放出了不少新产品和新功能,其中就包括 ...

  2. 转载:《TypeScript 中文入门教程》 10、混入

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 介绍 除了传统的面向对象继承方式,还流行一种通过可重用组件创建类的方式,就是联合另一个 ...

  3. Typescript Mixins(混合)

    除了惯例的面对对象的思想,另一种较流行的通过可复用组件创建类的方法是将简单的类混合到一起.你可能对这种混合的方式比较熟悉或对Scala语言的特性有理解,这种模式在JavaScript社区也有一定的人气 ...

  4. [TypeScript] Understanding Generics with RxJS

    Libraries such as RxJS use generics heavily in their definition files to describe how types flow thr ...

  5. 使用TypeScript拓展你自己的VSCode

    转自:http://www.iplaysoft.com/brackets.html使用TypeScript拓展你自己的VSCode! 0x00 前言在前几天的美国纽约,微软举行了Connect(); ...

  6. TypeScript: Angular 2 的秘密武器(译)

    本文整理自Dan Wahlin在ng-conf上的talk.原视频地址: https://www.youtube.com/watch?v=e3djIqAGqZo 开场白 开场白主要分为三部分: 感谢了 ...

  7. TypeScript为Zepto编写LazyLoad插件

    平时项目中使用的全部是jQuery框架,但是对于做webapp来说jQuery太过于庞大,当然你可以选择jQuery 2.*针对移动端的版本. 这里我采用移动端使用率比较多的zepto框架,他跟jqu ...

  8. TypeScript Vs2013 下提示Can not compile modules unless '--module' flag is provided

    VS在开发TypeScript程序时候,如果import了模块有的时候会有如下提示: 这种情况下,只需要对当前TypeScript项目生成设置为AMD规范即可!

  9. TypeScript

    TypeScript: Angular 2 的秘密武器(译)   本文整理自Dan Wahlin在ng-conf上的talk.原视频地址: https://www.youtube.com/watch? ...

  10. 打造TypeScript的Visual Studio Code开发环境

    打造TypeScript的Visual Studio Code开发环境 本文转自:https://zhuanlan.zhihu.com/p/21611724 作者: 2gua TypeScript是由 ...

随机推荐

  1. 原创软件 | 系统服务工具箱原创软件(587KB)--基于aardio开发的第一个程序

    1 系统服务工具箱简介 该软件是我使用aardio开发的第一个程序,它集成了多个系统常用的快捷键,无需记住各种命令就能快捷使用cmd管理员.计算机管理.控制面板.组策略.注册表.服务.任务管理.卸载程 ...

  2. oeasy教您玩转vim - 68 - # 标签页tab

    ​ tab选项卡 回忆上次 上次有三种批量替换,分别是 :windo :bufdo :argdo 执行的{cmd}可以用|按顺序增加 分别对应的 windows 窗口 buffers 缓存文件 arg ...

  3. Midnight Commander (MC)

    Midnight Commander GNU Midnight Commander 是一个可视化文件管理器,根据 GNU 通用公共许可证获得许可,因此有资格成为自由软件.它是一个功能丰富的全屏文本模式 ...

  4. VUE系列---深度解析 Vue 优化策略

    在前端开发中,性能优化一直是一个重要的课题.Vue.js 提供了多种优化策略,帮助开发者构建高性能的应用.本文将深入解析以下几个优化策略: 使用 v-once.v-if 和 v-show 的区别和优化 ...

  5. Java 监听POST请求

    要监听POST请求,我们可以使用Java中的HttpServlet类.以下是一个使用Servlet API监听POST请求的完整示例.这个示例使用了Servlet 3.1规范,不需要在web.xml中 ...

  6. 移植自淘宝店家的,硬件SPI通讯3.5寸TFT,LCD屏幕。MSPM0G3507

    适用MSPM0G3507 LP开发板 3.5寸TFTLCD屏,SPI通讯 项目是CCStheia的 特点:硬件SPI,速度更快,可以在syscfg中自行修改引脚 蓝奏云: https://wwo.la ...

  7. 【转载】逐际动力双足机器人P1在深圳塘朗山零样本、无保护、全开放完成测试

    原文: https://weibo.com/1255595687/O5k4Aj8l2 [逐际动力双足机器人P1在深圳塘朗山零样本.无保护.全开放完成测试] 上周,就在全球AI界被美国初创公司Figur ...

  8. 全球最大开源模型Grok-1 —— 马斯克 —— 自然语言大模型

    当前世界上参数最大的开源大语言模型Grok-1,参数权重大小为296GB,即3140亿参数,远远超过了OpenAI的GPT-3.5模型. 该模型采用的3140亿参数的MoE模型,在给定token上的激 ...

  9. 感慨!美国人的大学课程搞的确实蛮好的,不是那种刻板读书的感觉 —— 课程:SERVICE-ORIENTED COMPUTING AND SYSTEM INTEGRATION: SOFTWARE, IOT, BIG DATA, AND AI AS SERVICES

    无意间看到了一个美国人的课程,使用的教材:<SERVICE-ORIENTED COMPUTING AND SYSTEM INTEGRATION: SOFTWARE, IOT, BIG DATA, ...

  10. 解密prompt系列35. 标准化Prompt进行时! DSPy论文串烧和代码示例

    一晃24年已经过了一半,我们来重新看下大模型应用中最脆弱的一环Prompt Engineering有了哪些新的解决方案.这一章我们先看看大火的DSPy框架,会先梳理DSPy相关的几篇核心论文了解下框架 ...