Javascript 什么';什么是承诺的正确模式?

Javascript 什么';什么是承诺的正确模式?,javascript,c#,asynchronous,promise,deferred,Javascript,C#,Asynchronous,Promise,Deferred,我使用TypeScript和async/wait来表示异步工作流。该工作流的一部分是调用web工作人员,并在其返回结果时继续 在C#中,我将创建一个TaskCompletionSource,wait它的Task,代码中的其他地方将调用SetResult来解析TaskCompletionSource 在JavaScript中,我可以使用Promise.defer(),wait初始化一个延迟器对象,并在窗口中的Promise和其他地方进行初始化。onmessage侦听器将调用resolve(或rej

我使用TypeScript和
async
/
wait
来表示异步工作流。该工作流的一部分是调用web工作人员,并在其返回结果时继续

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

在JavaScript中,我可以使用
Promise.defer()
wait
初始化一个延迟器对象,并在
窗口中的
Promise
和其他地方进行初始化。onmessage
侦听器将调用
resolve
(或
reject
)方法以继续异步工作流

听起来不错,但是MDN说,
defer
已经过时了。使用
Promise
构造函数的建议解决方案,该构造函数让代理执行工作并调用
resolve
/
reject
方法,对我来说不起作用,因为我可能无法实现该逻辑,我只想在一个完全不同的词法范围内对对象调用
resolve
reject
,我不能用这个函数


有一个函数通过绑定
resolve
reject
函数为我提供了这样的对象,我可以在不改变代码语义的情况下使用这些函数。但这是一种不好的做法吗?有没有公认的更好的模式?JavaScript中的
TaskCompletionSource
的惯用等价物是什么?

只要您确定确实需要一个延迟的,那么使用延迟的助手绝对没有问题。在我所有的promise编程中,我只发现了一种情况,即我实际上需要一个延迟的构造函数,而不能仅仅重新构造代码以使用典型的promise构造函数模式

当创建promise/deferred对象的代码和解析或拒绝它的代码之间有一个单独的代码时,似乎就会出现我发现的情况和其他人指出的情况。通常情况下,您会将它们放在一起,但有时它们是完全不同的代码部分,并且有这样做的逻辑原因。在这些情况下,基于常规承诺构建的延迟对象可以是更干净的实现方法

下面是另一个简单的延迟实现,它也是向后和向前兼容的:

但这是一种不好的做法吗

我知道有些纯粹主义者认为你不应该这样做。但是,如果您确信这是实现代码的最干净、最简单的方法,并且使用典型的Promise构造函数executor回调实现代码并不那么实用,那么我想说这是一个非常好的实践。有些人甚至不想尝试或学习承诺的构建者/执行者,就想使用延迟承诺,这不是一个好的实践。出于各种原因,在实际情况下应使用promise构造函数

首选promise构造函数的一个重要原因是executor回调函数中所有promise特定的代码都是“抛出安全的”。如果在代码中抛出异常,它将自动被捕获并拒绝承诺(这是一件好事)。一旦您使用了一个延迟调用,并且有一堆代码在回调之外操纵承诺,它就不会自动抛出安全。事实上,您的代码甚至可以同步抛出,这对于调用方来说是一场噩梦。您可以在此处看到该问题的描述:。因此,延迟模式不是首选模式,但在适当的保护下,仍有一些情况(通常很少)会导致更干净的实现

有没有公认的更好的模式

答案和上面差不多。首选使用承诺构造函数/执行器,但在不实际的情况下(通常是代码的不同部分创建承诺,然后解决/拒绝),并且没有简单的方法重新组织代码以与承诺构造函数/执行器良好配合,那么延迟对象可能是首选实现。通常情况下,您会发现这些情况很少发生,因为大多数情况下,您都可以对代码进行结构化,以便相同的代码块正在创建和解决/拒绝承诺,而不需要延迟

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


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

这是一个令人惊讶的答案,感谢您投入了这么多时间。我无法想象在使用
Promise
构造函数执行器时,如何创建一个
Promise
在主窗口中等待并
从一个web工作者那里解析它(至少是一个不同的文件!),所以我想我可以使用
延迟
来实现这一点。@TomášHübelbauer-嗯,webWorker最终将不得不向主线程发送一条消息以与之通信,对吗?您能否让承诺执行人监听该消息,并在收到该消息时让其在执行人中解析承诺?我只是在这里猜测,因为我没有看到你的真实代码。想想看,我可以在executor实现中侦听消息,尽管目前我的消息处理器位于中心位置,这样我就必须将消息分解到每个executor。我会玩弄它,也许我忽略了什么。如果我没有想法或不确定,将发布一个问题。:)@TomášHübelbauer-执行器设计模式通常(尽管不总是)只需要一个reth