我理解通常只会在使用promises时附加带有then()
调用和链行为的延续代码。
但是,我想启动一个包含承诺的异步调用,然后分别启动一个3秒$timeout()
,这样我就可以采取UI操作,只要原始承诺尚未完成。 (我预计这只会发生在慢速连接,3G上的移动设备等)。
鉴于承诺,我可以检查它是否完整而没有阻塞或等待?
答案 0 :(得分:46)
我想这是在Angular的最新版本中添加的,但现在似乎在承诺上有一个$$状态对象:
var deferred = $q.defer();
console.log(deferred.promise.$$state.status); // 0
deferred.resolve();
console.log(deferred.promise.$$state.status); //1
如评论中所述,建议不要这样做,因为升级Angular版本时可能会中断。
答案 1 :(得分:36)
我认为你最好的选择,(不修改Angular源并提交拉取请求)是保留一个本地标志,如果承诺已经解决。每次设置您感兴趣的承诺时重置它,并在原始承诺的then()
中将其标记为完整。在$timeout
then()
中检查标志,以了解原始承诺是否已解决。
这样的事情:
var promiseCompleted = false;
promise.then(function(){promiseCompleted=true;})
$timeout(...).then(function(){if(!promiseCompleted)doStuff()})
Kris Kowal的实现包括检查承诺状态的其他方法,但不幸的是,Angular的$q
实现不包括这些。
答案 2 :(得分:8)
似乎没有可能,正如@shaunhusain已经提到过的那样。但也许没有必要:
// shows stuff from 3s ahead to promise completetion,
// or does and undoes it in one step if promise completes before
$q.all(promise, $timeout(doStuff, 3000)).then(undoStuff);
或者更好:
var tooSlow = $timeout(doStuff, 3000);
promise.always(tooSlow.cancel);
答案 3 :(得分:1)
我有一个类似的问题,我需要检查一个承诺是否已经返回。因为AngularJS的$watch
函数将在呈现页面时注册更改,即使新值和旧值都未定义,我还是要检查是否有任何值存储在我的外部模型中。
这绝对是一个黑客,但我这样做:
$scope.$watch('userSelection', function() {
if(promiseObject.hasOwnProperty("$$v"){
userExportableState.selection = $scope.userSelection;
}
};
我知道$$v
是AngularJS使用的内部变量,但它作为我们已解决的承诺的指标非常可靠。谁知道当我们升级到AngularJS 1.2时会发生什么: - /我没有看到在1.2文档中提及$q
的任何改进,但也许有人会写一个更接近Q的更好功能集的替代服务。
答案 4 :(得分:0)
我不知道您的具体情况,但更常见的是在进行异步调用(并生成承诺)后立即设置超时。
提供setTimeout()
语句与异步调用位于同一事件线程中,您无需担心竞争效应的可能性。由于javascript是严格单线程的,所以promise的.then()
回调可以保证在以后的事件线程中触发。