如何检查是否已解决Angular $ q promise

时间:2013-07-26 16:01:15

标签: angularjs promise q

我理解通常只会在使用promises时附加带有then()调用和链行为的延续代码。

但是,我想启动一个包含承诺的异步调用,然后分别启动一个3秒$timeout(),这样我就可以采取UI操作,只要原始承诺尚未完成。 (我预计这只会发生在慢速连接,3G上的移动设备等)。

鉴于承诺,我可以检查它是否完整而没有阻塞或等待?

5 个答案:

答案 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()回调可以保证在以后的事件线程中触发。