【问题标题】:Defer / postpone promise resolve推迟/推迟承诺解决
【发布时间】:2017-02-01 00:27:51
【问题描述】:

我想以与 Angular 的 defer.resolve 和 Javascript Promise 对象相同的方式解析一个 Promise 对象。 换句话说:我想创建一个要返回的虚拟承诺对象。此承诺将在稍后解决。

在 Angular 中我会这样写:

...
$scope.checkThis = { test: false };

function getPromise() {
    var deferred = $q.defer();
    var data = [1, 2, 3];

    function resolvePromise() {
        deferred.resolve(data);
    }

    $scope.$watch("checkThis.test", function(newVal, oldVal) {
        if (newVal) {
            resolvePromise();
        }
    });

    return deferred.promise;
}

$scope.getData1 = function() {
    return getPromise();
};

$scope.getData2 = function() {
    return getPromise();
};

...

如何使用普通的 Javascript Promise 对象实现相同的效果?我看不到如何使用 Promise 构造函数,因为有一个事件($scope.checkThis.test 变为 true)会触发多个解析。

【问题讨论】:

  • 您所说的“会触发多个解析的事件”是什么意思?为什么这对 deferred 有效,但对 promise 构造函数无效?

标签: javascript angularjs promise deferred resolve


【解决方案1】:

标准承诺使用revealing constructor pattern。有一种直接且首选的方法:

function getPromise() {
  return new Promise(resolve => {
    var data = [1, 2, 3];
    $scope.$watch("checkThis.test", function(newVal, oldVal) {
      if (newVal) {
        resolve(data);
      }
    });
  });
}

当心!标准承诺不会触发角度摘要循环,对承诺回调内的范围所做的更改可能不会立即反映在 UI 和观察者上。这就是你不能只将$q 承诺更改为标准Promises 的原因。

如果由于某种原因您无法将显示构造函数模式应用到您的场景中,这里有一种创建类似延迟类的方法。 请记住,您始终可以避免使用此类,我只是将其留在这里,以便访问者了解如何从旧的 Promise 库进行更改,而无需重组现有代码。没有新代码应该使用这个:

class Deferred {
  constructor() {
    this.resolve = null;
    this.reject = null;
    this.promise = null;

    this.promise = new Promise((resolve, reject) => {
      this.resolve = resolve;
      this.reject = reject;
    });
  }
}

【讨论】:

  • 好吧,这个Deferred 类消除了显示构造函数模式的所有优点。不要使用它!
  • 如果我理解正确,您正在创建一个返回未决承诺的 Promise 工厂。这适用于我的情况。谢谢你。 @Bergi:为什么不使用它?
  • @Bergi 完全正确。我只在涉及分布式系统的场景中使用它,并且必须将基于消息的协议转换为基于调用响应的协议。在这种情况下,唯一的方法是将所有待处理的请求(例如延迟请求)存储在映射中,并在适当的响应中检索和解决它们。
  • @casenonsensitive 请参阅 Domenic 博客答案中的链接,以及 this SO answer
  • @casenonsensitive 它不太直观且可读性较差。构造函数旨在使对象进入可用状态。但是Deferred 构造函数没有这样的事情。您仍然需要调用 deferred.resolve()deferred.reject() 才能使对象真正可用。此外,这些函数可以在程序中的任何位置调用,因此很难遵循。 Promise 构造函数保证解决/拒绝条件都在同一个地方,你可以从new Promise 返回的对象是一个完全可用的 Promise。
猜你喜欢
  • 1970-01-01
  • 2018-10-11
  • 1970-01-01
  • 1970-01-01
  • 2015-03-08
  • 2015-06-23
  • 2016-11-19
  • 1970-01-01
  • 2015-03-29
相关资源
最近更新 更多