该问题一般适用于承诺,并非特定于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并闻起来很糟糕。
答案 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()两次,让两个调用等待同一个异步操作。