什么时候需要创建延迟?

When would someone need to create a deferred?

现在通常不鼓励创建延迟对象,而倾向于使用 ES6 风格的 Promise 构造函数。是否存在需要(或以某种方式更好)使用延迟的情况?

例如,在 this page 上,给出以下示例作为使用延迟的理由:

function delay(ms) {
    var deferred = Promise.pending();
    setTimeout(function(){
        deferred.resolve();
    }, ms);
    return deferred.promise;
}

然而,这也可以通过 Promise 构造函数来完成:

function delay(ms) {
    return new Promise(function(resolve, reject){
        setTimeout(function(){
            resolve();
        }, ms);
    });
}

Native Promises 没有 deferred 开箱即用的所有内置方法,例如在其构造函数范围之外解析 Promise 的方法(尽管使用 Native Promise 很容易实现) ,以及查看 promise 状态的能力(虽然可以在开发工具中检查,但在本机 Promises 的常规 JavaScript 中是隐藏的)。

今天使用 deferred 的主要原因是向后兼容依赖于那些额外方法的代码。如果不进入意见领域,很难对您的问题给出明确的答案。

Does there exist a situation where it would be necessary (or just better somehow) to use a deferred?

没有这种情况需要延期。 "Better" 见仁见智,所以我不会在这里解决。

ES6 promise 规范没有延迟对象是有原因的。 你根本不需要一个。人们过去使用延迟对象的任何事情都可以总是用另一种不使用延迟对象的方式来完成延迟的对象。

首先,大多数用途非常适合 promise 构造函数模型。其次,任何其他不完全适合该模型的情况仍然可以使用 promise 构造函数或从已解决的 promise 开始并链接到它来完成。

我看到的延迟的主要用例是当您想将 resolve()reject() 的能力传递给除创建承诺。 Deferred 使这变得非常容易,因为您可以只传递延迟的对象,并且它有 public 方法来解决或拒绝它。但是,有了承诺,您也可以只传递 resolve and/or reject 方法。由于它们自动绑定到特定对象,您只需传递函数引用即可。并且,在其他情况下,您可以只让其他代码创建他们自己的承诺,然后 resolve/reject 自己创建,然后将该操作 link 发送到您的而不是让他们 resolve/reject 您的承诺。所有这些都像传递延迟对象一样干净吗?主要是见仁见智,但都不是很常见的用例,所有这些都可以在没有单独的延迟对象的情况下完成。

而且,正如 torazaburo 指出的那样,让一些外部代码解决或拒绝您的承诺本身就是一种反模式。你创造了承诺 - 你 resolve/reject 它。如果您想使用外部事件来决定何时 resolve/reject 它,然后让他们通知您(通过他们自己的承诺或回调),您可以 resolve/reject 您自己的承诺。或者,让他们创建自己的承诺供您使用。这确实是理想的模型。或者,让他们链接到您的承诺,以便最终结果由他们的操作完成时决定。

如果一个人习惯了使用延迟对象进行编码(比如使用 jQuery 延迟对象),那么在没有它的情况下可能需要一点时间来适应编码,但过了一会儿你就会开始有不同的想法并且使用 promise 构造函数开始变得自然。

一旦您承诺了您在任何给定应用程序中使用的异步操作范围,您就很少需要再创建自己的承诺,因为您大多只是构建您调用的异步函数的承诺已经在创建或使用像 Promise.all() 这样的流程控制操作,它为您创建了超级承诺。

这是反模式的要点。 使用已经为您创建的承诺,而不是手动创建更多承诺。 链接它们。 Return 承诺从 .then() 处理程序到 link 逻辑控制下的异步操作。

当然,有些现有的异步操作没有 return 承诺,有人需要为其创建承诺,但这应该在主要编码逻辑提供之外的某个地方的承诺层中完成并且只为该操作完成一次,然后调用异步操作的代码应该能够只使用 returned 承诺。