什么';这是Promise.dedefer的正确模式

本文关键字:模式 dedefer Promise 这是 什么 | 更新日期: 2023-09-27 17:59:27

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

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

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

听起来不错,但MDN说defer已经过时了。所提出的使用Promise构造函数的解决方案不适用于我,该构造函数由委托完成工作并调用resolve/reject方法,因为这种逻辑可能超出了我的能力范围,我只想在对象上以完全不同的词法范围调用resolvereject,我无法使用该函数做到这一点。

有一个前后兼容的帮助程序,它通过绑定resolvereject函数为我提供了这样的对象,我可以在不改变代码语义的情况下使用这些函数。但这是一种不好的做法吗?有公认的、更好的模式吗?JavaScript中TaskCompletionSource的惯用等效词是什么?

什么';这是Promise.dedefer的正确模式

只要你确定你真的需要一个递延的,那么做递延的助手绝对没有错。在我所有的promise编程中,我只发现了一种情况,即我实际上需要一个延迟的,并且不能仅仅重组我的代码来使用典型的promise构造函数模式。

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

这里有另一个简单的延迟实现,它也向后和向前兼容:

为什么Promise构造函数需要一个执行器?

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

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

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

有公认的、更好的模式吗?

和上面的答案差不多。首选的方法是使用promise构造函数/执行器,但在这种情况下(通常是代码的不同部分创建promise,然后解决/拒绝它),并且没有简单的方法来重组代码以与promise构造函数或执行器很好地协同工作,那么延迟对象可能是首选实现。通常情况下,你会发现这种情况很少见,因为大多数时候你可以构建代码,这样同一块代码就可以创建和解决/拒绝承诺,而不需要延迟。

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

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