创建者无法解决时的蓝鸟承诺模式

Bluebird promise pattern when creator cannot resolve

蓝鸟deprecated their Promise.defer() mechanism for various reasons。虽然我认为我了解延迟反模式的危险,但我想知道我的用例是否需要它。

我想 return 一个基于模态*的用户输入的 resolved/rejected 承诺。模态是非阻塞的,并且 return 本身不是一个承诺。相反,当用户点击他们的响应时,函数就会被调用。因此,构造 promise 的函数在其范围内没有足够的信息 resolve/reject。

Javascript

export class FooClass {

  canDeactivate() {
    this.modal.open();          

    this.deferred = Promise.defer();  
    return this.deferred.promise;

    // How can I use `new Promise(resolver_func)` without defer migration?
  }

  cancel() {
    this.deferred.reject();
  }

  discard() {
    this.deferred.resolve();
  }
}

HTML

<div id="modal" md-modal md-modal.ref="modal">
  <div class="modal-content">
    <h4>Modal Header</h4>
    <p>A bunch of text</p>
  </div>
  <div class="modal-footer">
    <a click.delegate="discard()" ...>Discard Changes</a>
    <a click.delegate="cancel()" ...>Stay on Page</a>
  </div>
</div>

*这是一个 Aurelia 应用程序,我的具体用例是 return 在 canDeactivate route lifecycle. A Materialize modal 期间出现的承诺,当用户试图离开时从页面询问他们是否要放弃更改并继续导航或留在页面上。

你可以这样做:

export class FooClass {

  canDeactivate() {
    this.modal.open();          

    //assign the promise to `this.promise` if you need access it later
    //you might not want to use `resolve` and `reject`. Choose better names 
    this.promise = new Promise((res, rej) => {
      this.resolve = res;
      this.reject = rej;
    });

    return this.promise;
  }

  cancel() {
    this.reject();
  }

  discard() {
    this.resolve();
  }
}

标准的 promise 执行器函数实际上只有两个选项。

  1. 您将调用 resolve/reject 的逻辑放在 promise 执行器函数中,因此您可以直接从那里调用 resolve/reject。

  2. 您通过将 resolve/reject 捕获到可从执行程序外部访问的变量中,公开了一种调用 resolve/reject 或导致其他东西从执行程序外部调用它的方法。

如果您想要构建代码的方式与选项 #1 不一致,并且您不想更改代码的结构方式,那么选项 #2 就是您剩下的经典的方法是使用延迟对象。

另一方面,几乎总有一种方法可以重构您的代码,使得 promise 执行器是围绕将触发 resolve/reject 的逻辑的闭包,并且可以在没有延迟的情况下解决问题。哪种方法更好取决于您的具体情况。我已经看到我称之为 deferreds 的合法案例,但它更像是 0.1% 的案例,而且大多数时候,对代码进行一些重构使其与 promise 的执行函数很好地对齐。

为了针对您的案例的具体情况提供想法,我们需要了解调用代码以了解如何在不使用延迟的情况下将整个操作变形以适应 promise 执行器。

例如,如果显示对话框的代码也是为取消和放弃按钮添加事件侦听器的代码(而不是将该代码嵌入 HTML),那么您可能可以将所有在 promise 执行器中编写代码并在没有延迟的情况下很好地解决你的问题,事实上,你的 HTML(不显眼 Javascript 的概念)中的更多代码通常被认为是一件好事。