【发布时间】:2018-03-03 00:14:26
【问题描述】:
在 async/await 之前,当我的代码使用回调时,我能够做三件事:(1) 使用结果调用回调,(2) 使用错误调用回调,或 (3) 不调用回调完全没有。
案例 (3) 用于以下情况:假设您有一个缩放按钮,用户可以单击它以更高分辨率渲染图像,这是一个异步过程。如果用户再次单击缩放按钮,则第一次渲染不再相关,可以取消以让新的缩放级别渲染运行。我通过从函数内部返回而不调用回调来处理这个问题,例如
if (process.wasCanceled()) {
return;
}
// ...
callback(someResult);
使用 async/await,您只能做两件事:返回或抛出。目前,我一直在使用 throw 来指示操作已取消,因为返回可能会错误地指示上游进程应该继续运行。但是抛出的问题是所有上游调用者都需要知道它本身并不是一个真正的错误,因此他们可能需要检查错误的类型。
我的另一个疯狂想法是创造一个永不回报的承诺。例如。 await never(),其中函数定义如下:
async function never () {
return new Promise(function () {});
}
这相当于不调用回调。
但我不知道这是否会一遍又一遍地泄漏内存。
如果没有我上面提到的缺点,有没有更好的等价物?
【问题讨论】:
-
我建议将 throw 与特定消息一起使用,例如“已取消”。是的,上游的一切都必须寻找这个......但这不是你想要的吗?
-
这是一个非常有趣的问题。我确实相信
never()出于内存泄漏原因是一个非常糟糕的主意。 @ControlAltDel 在我看来,他想要一个上游不必必须查看的情况,因为在他的第一个示例中,如果process.wasCanceled(),回调就不会运行。跨度> -
当我更多地考虑
await never()时,我认为它可能还可以。这两个问题(stackoverflow.com/questions/20068467 和stackoverflow.com/questions/38286358)似乎表明浏览器可能会垃圾收集由never函数创建的promise,因为promise 的函数中没有任何东西将它连接到堆的其余部分。所以也许它不会泄漏。 -
我没有看到抛出取消错误的问题。您的所有上游调用者都应该传播而无需您做任何事情,除了需要知道操作已取消的最顶层。
-
@ControlAltDel 我遗漏了架构的关键部分,即上游调用者创建 Process 对象并将其传递给被调用者。因此,可以取消被调用者的唯一方法是调用者(或其调用者之一)发起取消。所以呼叫者已经决定取消 - 它只是不知道。然而,这确实忽略了任何可能需要清理进程的中间函数,所以你说得很好。
标签: javascript callback async-await cancellation