Promise.defer的正确模式是什么? [英] What's the correct pattern for Promise.defer?

查看:354
本文介绍了Promise.defer的正确模式是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using TypeScript and async/await to represent an asynchronous workflow. Part of that workflow is to call out to a web worker and continue when it calls back with a result.

在C#中,我将创建一个 TaskCompletionSource await Task 以及代码中的其他地方将调用 SetResult 来解决 TaskCompletionSource

In C#, I'd create a TaskCompletionSource, await its Task and elsewhere in the code would call SetResult to resolve the TaskCompletionSource.

我可以在通过使用 Promise.defer() await 及其 Promise 和其他地方,在 window.onmessage 侦听器中,将调用 resolve (或 reject )方法使异步工作流继续进行。

I can do the same thing in JavaScript by initializing a Deferrer object using Promise.defer(), awaiting its Promise and elsewhere, in the window.onmessage listener would call the resolve (or reject) method to let the asynchronous workflow continue.

听起来不错,但MDN表示 defer 已过时。使用 Promise 构造函数的建议解决方案,该方法使委托人完成工作并调用 resolve / reject 方法对我不起作用,因为这种逻辑可能超出我的承受范围,我只想在对象上调用 resolve reject 在完全不同的词法范围内,我无法使用该函数来做到这一点。

Sounds lovely, but MDN says defer is obsolete. The proposed solution of using the Promise constructor which takes the delegate doing the work and calling the resolve/reject methods doesn't work for me, because that logic could be out of my reach, I just want on object to call resolve or reject on in an entirely different lexical scope, I can't do that with that function.

有一个<一个href = https://developer.mozilla.org/zh-CN/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred#Backwards_and_forwards_compatible_helper rel = nofollow>向后转发兼容帮助程序通过绑定 resolve reject 函数可以实现这样的对象,而无需更改代码的语义即可使用这些函数。但这是不好的做法吗?有没有公​​认的更好的模式?在JavaScript中, TaskCompletionSource 的惯用等效词是什么?

There's a Backwards and forwards compatible helper that gives me such object by binding the resolve and reject functions that I can use without chaning the semantics of my code. But is this a bad practice? Is there a recognized, better pattern? What's an idiomatic equivalent of TaskCompletionSource in JavaScript?

推荐答案

绝对有只要确定您确实需要延期,帮助者的延误就不会有任何问题。在我所有的Promise编程中,我只发现了一种情况,我实际上需要延期并且不能仅仅重组代码以使用典型的Promise构造函数模式。

There is absolutely nothing wrong with the helper that makes a deferred as long as you are sure you really need a deferred. In all my promise programming, I've only found one situation where I actually needed a deferred and couldn't just restructure my code to use the typical Promise constructor pattern.

当您将创建promise / deferred对象的代码与解析或拒绝该对象的代码分开时,似乎发现了我发现的情况以及其他情况。通常,您将它们放在一起,但是有时有时它们是完全不同的代码部分,因此有这样做的逻辑原因。在这种情况下,以常规诺言为基础的延迟对象可能是更清洁的实现方法。

It seems the situation I found and the one others have pointed to occurs when you have a separate between the code that creates the promise/deferred object and the code that resolves or rejects it. Usually, you have those together, but there are sometimes when they are completely different sections of code and there are logical reasons for doing it that way. In those cases, a deferred object built off a regular promise can be the cleaner method of implementation.

这里是另一个简单的Deferred实现,它也可以前后兼容:

Here's another simple Deferred implementation that is also backwards and forwards compatible:

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


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

But is this a bad practice?

我知道那里有一些纯粹主义者认为您永远不要这样做。但是,如果您确定这是实现代码的最干净,最简单的方法,并且使用典型的Promise构造函数执行器回调实现它并不实用,那我说这是一个很好的做法。有些人甚至在没有尝试或学习promise构造器/执行器的情况下都想使用延迟,这不是一个好习惯。出于各种原因,应在实际可行时使用promise构造函数。

I know there are some purists out there that think you should never do this. But, I'd say that it's a perfectly fine practice if you are sure that it is the cleanest and simplest way to implement your code and that implementing it with the typical Promise constructor executor callback just isn't as practical. There are those who want to use a deferred without even trying or learning the promise constructor/executor and that would not be a good practice. For a variety of reasons, the promise constructor should be used when practical.

首选promise构造函数的一个重要原因是执行器中的所有特定于promise的代码回调函数是抛出安全的。如果在该代码中引发了异常,它将自动被捕获并拒绝承诺(这是一件好事)。一旦使用了延迟并拥有一堆在该回调之外操纵承诺的代码,它就不会自动抛出安全。实际上,您的代码甚至可以同步抛出,这是调用者必须防范的噩梦。您可以在此处查看有关该问题的描述: https://stackoverflow.com/a/37657831/816620 。因此,延迟模式不是首选,但是在适当的保护下,仍然有一些情况(通常很少见)会导致更清洁的实现。

One big reason that the promise constructor is preferred is that all the promise-specific code in the executor callback function is "throw-safe". If an exception is thrown in that code, it will automatically be caught and reject the promise (which is a good thing). Once you use a deferred and have a bunch of code that manipulates the promise outside of that callback, it is not automatically throw-safe. In fact, your code can even throw synchronously which is a nightmare for callers to protect against. You can see a description of that issue here: https://stackoverflow.com/a/37657831/816620. So, the deferred pattern is not preferred, but with proper protections, there are still some cases (generally rare) where it leads to a cleaner implementation.


有公认的更好的模式吗?

Is there a recognized, better pattern?

与上述答案大致相同。首选是使用promise构造器/执行器,但是在这种情况不切实际的情况下(通常是代码的不同部分创建promise然后将其解析/拒绝),并且没有简单的方法来重新组织代码以使其正常工作Promise构造器/执行器,则延迟对象可能是首选实现。通常,您应该会发现这种情况很少见,因为在大多数情况下,您可以对代码进行结构化,以便相同的代码块可以创建和解决/拒绝承诺,而无需递延。

Pretty much the same answer as above. The preference is to use the promise constructor/executor, but in situations where that isn't practical (usually where different sections of code create the promise and then resolve/reject it) and there's no simple way to reorganize the code to work well with the promise constructor/executor, then a deferred object is likely the preferred implementation. You should generally find those situations rare because most of the time you can structure your code so the same chunk of code is creating and resolve/rejecting the promise and you don't need a deferred.


JavaScript中TaskCompletionSource的惯用法是什么?

What's an idiomatic equivalent of TaskCompletionSource in JavaScript?

等价于Javascript。这样一来,您就必须自己构建自己,而Promise是自然而然的方法,因为Promise是自然地表示完成或错误。您必须向我们展示您的实际代码,以便我们就是否可以在不使用延迟对象的情况下完全实现您的特定情况提供意见。

There is no built-in equivalent in Javascript. As such, you'd have to build your own and it seems like promises are a natural way to do so since they are naturally built to signal completion or error. You'd have to show us your actual code for us to offer an opinion on whether your specific situation can be implemented cleanly without using a deferred object.

这篇关于Promise.defer的正确模式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆