我正在学习AngularJs。我尝试创建一个非常简单的样本来理解Promise。 请参阅以下代码:
http://jsfiddle.net/HB7LU/3221/
的index.html:
<!doctype html>
<html ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script src="js/main.js"></script>
</head>
<body>
<div ng-controller="displayController">
<input id="Button1" type="button" value="Learn Promise" ng-click="Click()" />
</div>
</body>
</html>
main.js
var app = angular.module('myApp', []);
app.controller('displayController', function ($scope, $q) {
alert('Ctrl');
$scope.Click = function () {
alert('1');
var deferred = $q.defer();
var promisse= deferred.promise;
promisse.then(function (successResult) {
alert('Inside Promise success ' + successResult);
}, function (failureResult) {
alert('Inside Promise Failure ' + failureResult);
});
setTimeout(function () {
alert('2');
deferred.resolve('After timeout');
alert('3');
}, 1000);
}
});
在超时限制1000之后,我能够看到警报('2')和警报('3'),但是在promisse.then()内部没有警报。 为什么会这样?
答案 0 :(得分:2)
一些事情:
你正在使用javascript的setTimeout。我建议使用由角度提供的$timeout
。 (如果你真的想使用setTimeout,你必须做这样的事情:
setTimeout(function(){
$scope.$apply(function(){ deferred.resolve('resolving value'); });
}, 1000);
这是因为setTimeout超出了角度,并且它不知道应该解析promise(因为$ digest循环没有看到它已被更改)
此外,您不能拒绝已解决的承诺(反之亦然)。承诺只能被解决或拒绝一次。如果要在解析后拒绝承诺,则必须创建新的承诺对象。
看看这个小提琴:http://jsfiddle.net/hK9XW/2/
我在这里使用了$ timeout而不是setTimeout。
答案 1 :(得分:1)
由于resolve
功能未包含在Angular.JS摘要周期中,因此您需要将调用包裹在$rootScope.$apply()
内setTimeout
。但在您的情况下,更好的解决方案是简单地使用$timeout
服务,该服务保证在angular.js摘要周期内运行:
var app = angular.module('myApp', []);
app.controller('displayController', function ($scope, $q, $timeout) {
alert('Ctrl');
$scope.Click = function () {
alert('1');
var deferred = $q.defer();
var promisse= deferred.promise;
promisse.then(function (successResult) {
alert('Inside Promise success ' + successResult);
}, function (failureResult) {
alert('Inside Promise Failure ' + failureResult);
});
$timeout(function () {
alert('2');
deferred.resolve('After timeout');
alert('3');
}, 1000);
}
});
希望这有帮助!