簡體   English   中英

一次性解決承諾單例(角度服務)

[英]One-time resolving promise singleton (Angular service)

這個問題通常適用於promise,而並非特定於Angular,但是該示例使用了Angular $ q和服務單例。

這是一個矮人

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並聞起來很不好。

什么是使單例承諾僅在第一時間解決的好模式

要不要。 承諾的關鍵方面之一是,一旦它被解決,它就會被解決,並且被解決的狀態(已解決或被拒絕)和價值在那時都保持不變。 請參閱A + promises規范 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添加的回調,那不是一個承諾。 有點...其他

TJ Crowder是正確的,因為您在諾言中尋找的功能不存在。 但是,如何實現所需的問題可以在下面的結構中找到:

    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()將在第一次調用時返回約定的字符串。 后續調用返回null。

這個笨拙的人展示了上面的動作

編輯:哎呀,看錯了問題。


現在有一種使用EcmaScript Promise進行此操作的方法。 靜態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) { ... })

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM