首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Go的Defer语句的TypeScript等价物

Go的Defer语句的TypeScript等价物
EN

Stack Overflow用户
提问于 2020-03-25 19:25:06
回答 3查看 440关注 0票数 3

TypeScript有没有类似于Go的Defer语句?

我厌倦了在一个函数中的多个位置编写清理代码。寻找更简单的解决方案。

我在谷歌上快速搜索了一下,但什么也没找到。

EN

回答 3

Stack Overflow用户

发布于 2020-03-25 19:31:43

可以说答案是否定的,但你至少有几个选择:

  1. 正如@bereal提到的,你可以使用一个try/finally来实现。Re try/finally,你在评论中说:

是的,除非我不想使用try catch块,因为它们可能很昂贵。

不怎么有意思。抛出异常的开销很大,而进入try块则不是。finally块有轻微的开销,但我最近不得不在几个现代引擎中测量这一点,这真的是令人惊讶的微不足道。

  1. 您可以将一个函数赋给一个变量,然后在该函数的末尾运行它(或者,如果您想执行多个操作,也可以使用一个数组)。对于单一的清理,我希望它比try/finally更昂贵。对于多个(否则将需要嵌套的try/finally块),那么,您必须找出答案。

FWIW,一些例子:

try/finally中执行一次清理

代码语言:javascript
运行
复制
function example() {
    try {
        console.log("hello");
    } finally {
        console.log("world");
    }
}
example();

try/finally中的多重清理

代码语言:javascript
运行
复制
function example() {
    try {
        console.log("my");
        try {
            console.log("dog");
        } finally {
            console.log("has");
        }
    } finally {
        console.log("fleas");
    }
}
example();

通过赋值函数进行单次清理:

代码语言:javascript
运行
复制
function example() {
    let fn = null;
    fn = () => console.log("world");
    console.log("hello");
    if (fn) { // Allowing for the above to be conditional, even though
              // it isn't above
        fn();
    }
}
example();

try/finally中的多重清理

代码语言:javascript
运行
复制
function example() {
    const cleanup = [];
    cleanup.push(() => console.log("has"));
    console.log("my");
    cleanup.push(() => console.log("fleas"));
    console.log("dog");
    cleanup.forEach(fn => fn());
}
example();

或者以另一种顺序:

代码语言:javascript
运行
复制
function example() {
    const cleanup = [];
    cleanup.push(() => console.log("fleas"));
    console.log("my");
    cleanup.push(() => console.log("has"));
    console.log("dog");
    while (cleanup.length) {
        const fn = cleanup.pop();
        fn();
    }
}
example();

票数 1
EN

Stack Overflow用户

发布于 2021-08-01 06:36:57

我想要的是一种更清晰的方式来完成与TypeScript中的Go相同的defer工作:

代码语言:javascript
运行
复制
class Test {

  @Defer()
  async test () {
    const timer = setInterval(() => console.log('interval'), 1000)
    defer.call(this, () => clearInterval(timer))
    await new Promise(resolve => setTimeout(resolve, 1500))
  }

}

const t = new Test()
t.test()
  .catch(console.error)

在上面的代码中,我们定义了一个每隔1秒输出intervaltimer,并定义了一个在超出此函数范围时清除intervaldefer (与Go相同)。

当运行它时,await new Promise(resolve => setTimeout(resolve, 1500)将等待1.5秒,这将输出一行interval输出,然后程序退出。

代码语言:javascript
运行
复制
$ ts-node src/defer.ts 
interval
$

下面的代码示例是完整的代码,可以在TypeScript 4.4中通过复制/粘贴直接运行:

代码语言:javascript
运行
复制
const DEFER_SYMBOL = Symbol('defer')

type Callback = (err?: Error) => void

interface DeferizedThis {
  [DEFER_SYMBOL]?: Callback[],
}

function Defer () {
  return function callMethodDecorator (
    _target      : any,
    _propertyKey : string,
    descriptor   : PropertyDescriptor,
  ): PropertyDescriptor {

    const oldValue = descriptor.value

    async function deferizedMethod (
      this: DeferizedThis,
      ...args: any[]
    ) {
      try {
        const ret = await oldValue.apply(this, args)
        return ret
      } finally {
        if (this[DEFER_SYMBOL]) {
          const deferCallbacks = this[DEFER_SYMBOL]

          while (true) {
            const fn = deferCallbacks?.pop()
            if (!fn) { break }
            try { fn() } catch (e) { console.error(e) }
          }
        }
      }
    }

    descriptor.value = deferizedMethod
    return descriptor
  }
}

function defer (
  this: any,
  cb: Callback,
): void {
  if (this[DEFER_SYMBOL]) {
    this[DEFER_SYMBOL]!.push(cb)
  } else {
    this[DEFER_SYMBOL] = [cb]
  }
}

class Test {

  @Defer()
  async test () {
    const timer = setInterval(() => console.log('interval'), 1000)
    defer.call(this, () => clearInterval(timer))
    await new Promise(resolve => setTimeout(resolve, 1500))
  }

}

const t = new Test()
t.test()
  .catch(console.error)

如果你读过上面的代码,它显然是一个有be的PoC,绝对不能在生产中使用。

我想讨论一下,如果我们在TypeScript中有任何好的方法来实现这一点,通过遵循这个装饰器的方式,或者任何其他方向。

票数 0
EN

Stack Overflow用户

发布于 2021-10-24 23:20:11

也许这会有所帮助,来自原始的T.J. Crowder(@t-j-crowder)回复。

通过引用try/catch块的finally块中的变量来延迟

代码语言:javascript
运行
复制
function example() {
    const defers = [];
    try {
        var xx = "Firts";
        defers.push(((text) => () => console.log(text))(xx));
        xx = "No Firts";
        var yy = "Last";
        defers.push(((text) => () => console.log(text))(yy));
        yy = "No Last"
        const timer = setInterval(() => console.log('live'), 1000);
        defers.push(((t) => () => clearInterval(t))(timer));
    } finally {
        while (defers.length) {
            const fn = defers.pop();
            fn();
        }
    }
}
example();

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60847836

复制
相关文章

相似问题

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