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

时间:2016-08-01 17:29:48

标签: javascript c# asynchronous promise deferred

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

在C#中,我创建了TaskCompletionSourceawaitTask,代码中的其他位置会调用SetResult来解析TaskCompletionSource

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

听起来很可爱,但MDN说reject已经过时了。使用defer构造函数的建议解决方案使代理人完成工作并调用Promise / resolve方法对我来说不起作用,因为该逻辑可能不在我的目标,我只想让对象在一个完全不同的词汇范围内调用rejectresolve,我无法使用该功能。

有一个Backwards and forwards compatible helper通过绑定我可以使用的rejectresolve函数来提供这样的对象,而无需查询我的代码的语义。但这是一种不好的做法吗?有没有公​​认的,更好的模式?什么是JavaScript中reject的惯用等价物?

1 个答案:

答案 0 :(得分:2)

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

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

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

Why does the Promise constructor need an executor?

  

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

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

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

  

是否有一个公认的,更好的模式?

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

  

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

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