首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IDisposable / RAII在TypeScript?

IDisposable / RAII在TypeScript?
EN

Stack Overflow用户
提问于 2017-12-13 08:40:26
回答 3查看 2.6K关注 0票数 6

在TypeScript中实现确定性清理的惯用方式是什么?换句话说,是否有相当于C#的using (IDisposable)或C++的RAII?

还是我应该坚持finally

上下文:在SPA应用程序(Aurelia / ASP.NET Core )中,我试图给用户一个指示,说明当前正在从Web中获取数据。一旦完成了提取,即使抛出了异常,我也希望删除UI指示。我正在研究如何将它封装到一个"RAII类“中,以便于重用和更干净的语法(所以我不必用finally来修饰代码).

EN

回答 3

Stack Overflow用户

发布于 2017-12-13 11:40:13

在类型记录中没有using语句,您可以始终回到try-finally,这是using在C#中的语法糖。

另一种方法是使用函数创建自己的using

代码语言:javascript
复制
interface IDisposable {
    dispose();
}

function using<T extends IDisposable,
    T2 extends IDisposable,
    T3 extends IDisposable>(disposable: [T, T2, T3], action: (r: T, r2: T2, r3: T3) => void);
function using<T extends IDisposable, T2 extends IDisposable>(disposable: [T, T2], action: (r: T, r2: T2) => void);
function using<T extends IDisposable>(disposable: T, action: (r: T) => void);
function using(disposable: IDisposable[], action: (...r: IDisposable[]) => void)
function using(disposable: IDisposable | IDisposable[], action: (...r: IDisposable[]) => void) {
    let disposableArray = disposable instanceof Array ? disposable : [disposable];
    try {
        action(...disposableArray);
    } finally {
        disposableArray.forEach(d => d.dispose());
    }
}


// Usage
class UserNotify { dispose() { console.log("Done"); } }

class Other { dispose() { console.log("Done Other"); } }

using(new UserNotify(), userNotify => {
    console.log("DoStuff");
})
// It will type the arrow function parameter correctly for up to 3 parameters, but you can add more overloads above.
using([new UserNotify(), new Other()], (userNotify, other) => {
    console.log("DoStuff");
})

如果您想将它与承诺一起使用,您可以创建一个异步版本,其中一次性返回一个承诺,action参数也返回一个承诺:

代码语言:javascript
复制
interface IDisposableAsync {
    dispose(): Promise<void> | void;
}
function usingAsync<T extends IDisposableAsync, T2 extends IDisposableAsync, T3 extends IDisposableAsync>(disposable: [T, T2, T3], action: (r: T, r2: T2, r3: T3) => Promise<void>): Promise<void>;
function usingAsync<T extends IDisposableAsync, T2 extends IDisposableAsync>(disposable: [T, T2], action: (r: T, r2: T2) => Promise<void>): Promise<void>;
function usingAsync<T extends IDisposableAsync>(disposable: T, action: (r: T) => Promise<void>): Promise<void>;
function usingAsync(disposable: IDisposableAsync[], action: (...r: IDisposableAsync[]) => Promise<void>): Promise<void>
async function usingAsync(disposable: IDisposableAsync | IDisposableAsync[], action: (...r: IDisposableAsync[]) => Promise<void>): Promise<void> {
    let disposableArray = disposable instanceof Array ? disposable : [disposable];
    try {
        await action(...disposableArray);
    } finally {
        for (let d of disposableArray) {
            let result = d.dispose();
            if (result !== null) {
                await result;
            }
        }
    }
}

// Usage
class UserNotify { dispose() { console.log("Done"); } }
class Other { dispose() { console.log("Done Other"); } }
function delay() {
    return new Promise((r)=> setTimeout(() => {
        r();
    }, 100));
}
(async function () {
    await usingAsync(new UserNotify(), async userNotify => {
        await delay()
        console.log("DoStuff");
    })

    await usingAsync([new UserNotify(), new Other()], async (userNotify, other) => {
        await delay()
        console.log("DoStuff");
    })
})();
票数 2
EN

Stack Overflow用户

发布于 2019-03-07 16:31:29

不幸的是,它没有语言语句(比如析构函数和确定性销毁)。为此您必须使用try { ... } finally { ... }语句。

如果您想知道如何以类似于C++的方式来完成这个任务,请看一下https://github.com/cardinalby/ts-raii-scope,当我尝试使用RAII和TypeScript装饰器时。但我不确定它对生产代码是否有好处,因为其他开发人员可能会与这种方法混淆。

另外,我认为它可以由TypeScript变换实现。

票数 0
EN

Stack Overflow用户

发布于 2022-02-17 18:55:11

您可以使用WeakRef和计时器来检查对象是否存在。

代码语言:javascript
复制
function registerObject(object) {
    console.log('Start!')
    const ref = new WeakRef(object)
    const id = setInterval(() => {
      // Check if object does not exist anymore
      if (!ref.deref()) {
        console.log('End!')
        clearInterval(id)
      }
      console.log(`${typeof ref.deref()}`)
    }, 1000)
}

{
  let a = new Date();
  registerObject(a)
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47788722

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档