一次性解决承诺单身人士(Angular服务)

时间:2015-08-16 16:34:42

标签: javascript angularjs promise angular-promise

该问题一般适用于承诺,并非特定于Angular,但该示例使用Angular $ q和服务单例。

这是a plunker

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并闻起来很糟糕。

4 个答案:

答案 0 :(得分:4)

  

使单身人士承诺第一次解决的好方法

不要。承诺的一个关键方面是,一旦它得到解决,它就会得到解决,而已解决的状态(已解决或被拒绝)和价值在这一点上都是不变的。见the A+ promises spec的§2.1.2和§2.1.3:

  

2.1.2满足后,承诺:

     

2.1.2.1不得过渡到任何其他州。

     

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

     

2.1.3被拒绝时,承诺:

     

2.1.3.1不得过渡到任何其他州。

     

2.1.3.2必须有一个原因,不得改变。

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

答案 1 :(得分:1)

T.J。 Crowder是正确的,因为您在promise中寻找的功能不存在。然而,如何实现您正在寻找的东西的问题可以在如下结构中找到:

    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这一次(作为角度服务),GetValue()将在第一次调用时返回promisified字符串。后续调用返回null。

This plunker显示了上述内容

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

修改:哎呀,误读了这个问题。

现在有一种方法可以用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()两次,让两个调用等待同一个异步操作。