一次性解析承诺单例(Angular service)
One-time resolving promise singleton (Angular service)
这个问题适用于一般的承诺,而不是特定于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; 2.1.2.1不能转换到任何其他状态。>
2.1.2.2必须有一个值,这个值不能改变。
2.1.3当被拒绝时,承诺:
<nbsp; 2.1.3.1不能转换到任何其他状态。>
2.1.3.2必须有一个理由,不能改变。
如果通过then
添加的回调在某个阶段(例如,你的第二次连接)不满意,它不是一个承诺。这是…。
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) { ... })
- 测试Angular Service解决错误回调中的promise
- 控制器无法访问Angular Service变量
- Angular Service数据未在$scope中更新
- 在Angular Service/Controller中实现安全$apply的最佳方法
- 为什么要使用Angular Service来收集信息,而不仅仅是$http
- Angular-Service Array.filter vs basic for loop
- Angular service/value 不会从 $(document).ready() 中获取新的变量
- Angular Service中的异步定时问题
- 在Angular Service中获取数据并将其传递给另一个控制器
- Angular Service在返回promise时抛出异常
- 将Angular Service对象绑定到控制器作用域并更新
- 如何引用Angular Service返回的数组,以便维护状态
- Angular Service可以从一个控制器中设置数据,但不能从另一个控制器中设置
- Angular Service中带有2个控制器的Javascript Getter/Setter
- Angular JS SPA:如何使用Angular Controller SPA来调用Angular service
- 在Angular Service中找不到方法
- Angular Service创建的函数需要此关键字
- 用angular service + jasmine测试404失败响应
- 在Angular Service中使用$http -无法读取property 'post'的定义
- Angular Service可以在控制器中调用调用该服务的函数吗?