一次性解析承诺单例(Angular service)

One-time resolving promise singleton (Angular service)

本文关键字:Angular service 单例 承诺 一次性      更新时间:2023-09-26

这个问题适用于一般的承诺,而不是特定于Angular,但是这个例子使用了Angular的$q和service单例。

这是一个活塞

var app = angular.module('app', []);
app.factory('onetimeResolvingService', function ($q) {
  var promise = $q(function(resolve, reject) {
    setTimeout(function () {
      resolve();
    }, 500);
  });
  return promise;
});
app.controller('AController', function (onetimeResolvingService, $q) {
  onetimeResolvingService.then(function () {
    console.log('A resolved');
    return $q.reject();
  }).then(function () {
    console.log('A resolved');
  });
});
app.controller('BController', function (onetimeResolvingService, $q) {
  onetimeResolvingService.then(function () {
    console.log('B resolved');
    return $q.reject();
  }).then(function () {
    console.log('B resolved');
  });
});

,文档是

  <body ng-app="app">
    <div ng-controller="AController"></div>
    <div ng-controller="BController"></div>
  </body>

它会自然输出

解决B

解决

使单例承诺只在第一次解析的好模式是什么,即

解决

而不是之后的时间?

onetimeResolvingService.$$state.status = 2这样的东西可能可以做到这一点,但它看起来像$q hack,而且闻起来很难闻。

使单例承诺仅在第一次解析时才解析的好模式是什么呢

To not To。承诺的一个关键方面是,一旦它被解决,它就被解决了,并且解决的状态(解决或拒绝)和值在那时都是不变的。参见A+承诺规范的§2.1.2和§2.1.3:

2.1.2承诺实现时:

<nbsp;&nbsp;2.1.2.1不能转换到任何其他状态。>

  2.1.2.2必须有一个值,这个值不能改变。

2.1.3当被拒绝时,承诺:

<nbsp;&nbsp;2.1.3.1不能转换到任何其他状态。>

  2.1.3.2必须有一个理由,不能改变。

如果通过then添加的回调在某个阶段(例如,你的第二次连接)不满意,它不是一个承诺。这是…。

<p克劳德是正确的,因为你在承诺中寻找的功能并不存在。然而,如何实现你正在寻找的问题可以在下面的结构中找到:>
    function OnetimeValue($q) {
        var promisedValue = $q(function(resolve, reject) {
            setTimeout(function () {resolve('The one time value');}, 500);
        });
        var valueGot = false;
        this.GetValue = function GetValue() {
            var res;
            if (!valueGot) {
                res = promisedValue;
            } else {
                res = $q(function(resolve, reject) {
                    resolve(null);
                });
            }
            valueGot = true;
            return res;
        };
    }

假设你只new一次(就像angular服务一样),GetValue()将在第一次调用时返回承诺的字符串。后续调用返回null。

这个活塞显示了上面的动作

编辑:哎呀,看错问题了


现在有一种方法可以用EcmaScript承诺做到这一点。静态promise .resolve()方法接受一个promise并等待它的值;如果它已经被解析过,它就返回值。

例如,下面是我们如何使用这个方法来多次调用fetchQuery依赖于一个异步身份验证调用:

fetchQuery获取一个授权令牌(JWT):

const authToken = await AuthToken.get();

AuthToken看起来像(TypeScript):

class AuthToken {
  private static _accessTokenPromise: Promise<string>;
  public static async get() {
    if (!this._accessTokenPromise)
      this._accessTokenPromise = this.AuthFunction(); // AuthFunction returns a promise
    return await Promise.resolve(this._accessTokenPromise);
  }
}

或者根据OP的问题在同一个promise对象上调用两次then(),以使两个调用等待同一个异步操作。

如果你使用的是lodash,你可以简单地使用memoize,像这样:

const returnFirstRunResultAlways = _.memoize(async function(params) { ... })