[英]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.