gpt4 book ai didi

javascript - 如何中断或取消 promise 以清理在 JavaScript/TypeScript 中异步创建的多个对象

转载 作者:行者123 更新时间:2023-11-30 11:36:12 57 4
gpt4 key购买 nike

注意:我的代码恰好是用 TypeScript 编写的,但这个问题适用于 TypeScript 和 JavaScript,只是进行了一些语法更改。

我有一个类订阅了一些东西(例如高速公路消息)。当我处理完该对象后,我需要取消订阅所有内容。一般来说,我的代码是这样的:

class Example {
private sub1: Subscription;
private sub2: Subscription;
private sub3: Subscription;

constructor() {
subscribeToThings();
}

async subscribeToThings() {
this.sub1 = await subscribeToThingOne();
this.sub2 = await subscribeToThingTwo();
// *** NOTE 1 ***
this.sub3 = await subscribeToThingThree();
}

cleanupOnDeath () {
this.sub1.unsubscribe();
this.sub2.unsubscribe();
this.sub3.unsubscribe();
}
}

当我不再需要这个对象时,我调用cleanupOnDeath

但是,有一个问题。如果订阅(异步)需要很长时间,则可能会在所有 sub1sub2 之前调用“cleanupOnDeath()”函数>sub3 已设置。例如,调用 cleanupOnDeath 时,代码可能位于标记为 *** NOTE 1 *** 的行。

当然我可以在调用unsubscribe 之前检查每个订阅是否未定义,但这并没有真正解决问题 因为那时第三个订阅得到处理 < em>after cleanupOnDeath 完成后,将永远存在。

有没有一种方法可以实现此代码,以便可以在 subscribeToThings() 的中间调用 cleanupOnDeath() 而不会使代码异常复杂?

我能想出的最简单的解决方案是这样的(根据需要替换上面代码的部分):

    constructor() {
this.subscribeAndUnsubscribe();
}

async subscribeAndUnsubscribe () {
await this.subscribeToThings();

await cleanupEvent.wait();

this.sub1.unsubscribe();
this.sub2.unsubscribe();
this.sub3.unsubscribe();
}

cleanupOnDeath() {
cleanupEvent.set();
}

cleanupEvent 是某种同步原语。但我不认为这是最佳的,因为它还要求在取消订阅之前完成所有未决订阅。理想情况下,我希望能够尽早中止 subscribeToThings(),而无需在每行代码之后添加检查。例如。可以这样做:

    completed:boolean = false;

async subscribeToThings() {
try {
this.abortIfDone();
this.sub1 = await subscribeToThingOne();
this.abortIfDone();
this.sub2 = await subscribeToThingTwo();
this.abortIfDone();
this.sub3 = await subscribeToThingThree();
} catch (abortedEarly) {
// Something here
}
}

abortIfDone() {
if (this.completed) throw 'Something';
}

cleanupOnDeath() {
this.completed = true;
if (this.sub1) this.sub1.unsubscribe();
if (this.sub1) this.sub2.unsubscribe();
if (this.sub1) this.sub3.unsubscribe();
}

但这很困惑和复杂。

编辑 - 解决方案

根据@ChrisTavares 的回答,我最终使用了以下代码。这和他的回答之间的区别在于我不再等待任何事情或自己存储订阅。之前,我一直在等待他们获取底层订阅对象,其唯一目的是稍后取消订阅。由于此代码存储 promise 并处理使用 then 取消订阅的 promise ,因此没有必要这样做。

class Example {
private sub1Promise: Promise<Subscription>;
private sub2Promise: Promise<Subscription>;
private sub3Promise: Promise<Subscription>;

constructor() {
this.subscribeToThings();
}

subscribeToThings() {
// No longer async!
this.sub1Promise = subscribeToThingOne();
this.sub2Promise = subscribeToThingTwo();
this.sub3Promise = subscribeToThingThree();
}

cleanupOnDeath () {
this.sub1Promise.then(s => s.unsubscribe());
this.sub2Promise.then(s => s.unsubscribe());
this.sub3Promise.then(s => s.unsubscribe());
}
}

最佳答案

没有取消 promise 的标准方法 - 各个规范委员会都在进行讨论,但由于很多原因在这里无济于事,这是一个难题。

我怀疑这是否是一个合理的问题 - 订阅真的慢到足以担心这个问题吗?我对高速公路不熟悉。

但是,假设是这样,可以做的一件事是不要立即 await 东西,而是坚持实际的 promise 。然后你可以添加一个 .then 处理程序来在需要的时候清理东西。像这样:

class Example {
private sub1: Subscription;
private sub2: Subscription;
private sub3: Subscription;

private sub1Promise: Promise<Subscription>;
private sub2Promise: Promise<Subscription>;
private sub3Promise: Promise<Subscription>;

constructor() {
subscribeToThings();
}

async subscribeToThings() {
// *** NOTE - no await here ***
this.sub1Promise = subscribeToThingOne();
this.sub2Promise = subscribeToThingTwo();
this.sub3Promise = subscribeToThingThree();

this.sub1 = await this.sub1Promise;
this.sub2 = await this.sub2Promise;
this.sub3 = await this.sub3Promise;
}

cleanupOnDeath () {
// Unsubscribe each promise. Don't need to check for null,
// they were set in subscribeToThings
this.sub1Promise.then((s) => s.unsubscribe());
this.sub2Promise.then((s) => s.unsubscribe());
this.sub3Promise.then((s) => s.unsubscribe());
}
}

关于javascript - 如何中断或取消 promise 以清理在 JavaScript/TypeScript 中异步创建的多个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44317032/

57 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com