【发布时间】:2014-08-27 13:45:44
【问题描述】:
我有一个递归函数每半秒左右检查一些数据。该函数返回一个承诺。找到数据后,我想解决承诺并将数据作为解决方案传递。问题是,promise 不会在函数之外调用 .then() 。这是小提琴:http://jsfiddle.net/btyg1u0g/1/。
这是小提琴代码:
服务:
myApp.factory('myService', function($q, $timeout) {
var checkStartTime = false;
var checkTimeout = 30000;
function checkForContent() {
var deferred = $q.defer();
// simulating an $http request here
$timeout(function () {
console.log("Checking...");
if (!checkStartTime) checkStartTime = new Date();
// this would normally be 'if (data)'
if ((new Date()) - checkStartTime > 3000) {
deferred.resolve("Finished check");
checkStartTime = false; // reset the timeout start time
} else {
// if we didn't find data, wait a bit and check again
$timeout(function () {
checkForContent();
}, 400);
}
}, 5);
// then is called in here when we find data
deferred.promise.then(function(message) {
console.log("Resolved inside checkForContent");
});
return deferred.promise;
}
return {
runCheck: function() {
return checkForContent()
}
}
});
控制器:
myApp.controller('MyCtrl', function ($scope, myService) {
$scope.name = 'Superhero';
// then is never called
myService.runCheck()
.then(function (message) {
console.log("Resolved outside checkForContent");
});
});
【问题讨论】:
-
它调用了 checkForContent 里面的那个。它没有调用控制器中的那个。我应该看到两个日志:“Resolved inside checkForContent”和“Resolved outside checkForContent”。
-
你做错了......你永远不会解决你最初返回的承诺。每次函数创建一个新的 Promise 并且最后一个 Promise 被解决,你已经将它链接到你的函数中。但是函数调用期间返回的承诺从未得到解决。
-
啊,我明白了,我没有意识到我每次都在创造一个新的承诺。我想你有它,但让我测试一下。
-
function checkForData(){ return $q.when().then(function poll(){ return data || $timeout(400).then(poll); })- 为您解决了这个问题。该代码没有理由超过 3 行。$timeout已经返回了一个承诺,承诺链,你有一个延迟的反模式。 -
@RobbyAllsopp 是 you looking for a retry logic 吗?像这样的东西? plnkr.co/edit/S6oIeF?p=preview