Promise.defer的正确模式是什么?

我正在使用TypeScript和async / await来表示异步工作流。 该工作流程的一部分是呼叫Web工作者,并在回调结果时继续。

在C#中,我创建了一个TaskCompletionSourceawait它的Task ,代码中的其他地方会调用SetResult来解析TaskCompletionSource

我可以在JavaScript中做同样的事情,通过使用Promise.defer()初始化Deferrer对象, awaitPromise和其他地方,在window.onmessage监听器中将调用resolve (或reject )方法让异步工作流继续。

听起来很可爱,但MDN说defer已经过时了。 使用Promise构造函数的提议解决方案使Promise执行工作并调用resolve / reject方法对我不起作用,因为该逻辑可能超出我的范围,我只想在对象上调用resolvereject on在一个完全不同的词汇范围内,我不能用那个function做到这一点。

有一个向后兼容的帮助器 ,它通过绑定我可以使用的resolvereject函数来给我这样的对象,而无需查询我的代码的语义。 但这是一种不好的做法吗? 有没有公​​认的,更好的模式? 什么是JavaScript中TaskCompletionSource的惯用等价物?

只要你确定你确实需要延期,那么助手就没有任何问题。 在我的所有承诺编程中,我只发现了一个实际需要延迟的情况,并且不能只重构我的代码以使用典型的Promise构造函数模式。

当你在创建promise / deferred对象的代码和解析或拒绝它的代码之间分开时,我发现并且其他人指出的情况似乎发生了。 通常,你将它们放在一起,但有时它们是完全不同的代码部分,并且有合理的理由这样做。 在这些情况下,构建常规承诺的延迟对象可以是更清晰的实现方法。

这是另一个简单的延迟实现,它也是向后兼容的:

为什么Promise构造函数需要执行程序?

但这是一种不好的做法吗?

我知道那里有一些纯粹主义者认为你永远不应该这样做。 但是,我认为如果你确定它是实现代码的最简洁和最简单的方法,并且使用典型的Promise构造函数执行程序回调实现它并不实际,那么这是一个非常好的实践。 有些人想要使用延迟,甚至没有尝试或学习承诺构造函数/执行者,这不是一个好习惯。 出于各种原因,应该在实际使用promise构造函数。

promise构造函数首选的一个重要原因是执行程序回调函数中所有特定于promise的代码都是“throw-safe”。 如果在该代码中抛出exception,它将自动被捕获并拒绝承诺(这是一件好事)。 一旦你使用了延迟并拥有一堆操作该回调之外的promise的代码,它就不会自动抛出安全。 事实上,你的代码甚至可以同步抛出,这对于呼叫者来说是一个噩梦。 您可以在此处查看该问题的说明: https : //stackoverflow.com/a/37657831/816620 。 因此,延迟模式不是首选,但如果有适当的保护措施,仍有一些情况(通常很少见)会导致更清洁的实施。

有没有公​​认的,更好的模式?

与上面几乎相同的答案。 首选是使用promise构造函数/执行器,但是在不实用的情况下(通常在代码的不同部分创建承诺然后解析/拒绝它)并且没有简单的方法来重新组织代码以便与promise构造函数/执行器,然后延迟对象可能是首选实现。 您通常应该发现这些情况很少见,因为大多数情况下您可以构建代码,因此相同的代码块正在创建并解决/拒绝承诺,并且您不需要延迟。

什么是JavaScript中TaskCompletionSource的惯用等价物?

Javascript中没有内置的等价物。 因此,你必须建立自己的,似乎承诺是一种自然的方式,因为它们自然地构建为信号完成或错误。 您必须向我们展示您的实际代码,以便我们就您是否可以在不使用延迟对象的情况下干净地实施您的具体情况提供意见。