javascript AngularJS,具有递归函数的承诺
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20607313/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AngularJS, promise with recursive function
提问by Fauphi
I'm trying to use the AngularJS promise/then with a recursive function. But the then-function is not called (none of the error-, success-, notify-callbacks gets called).
我正在尝试将 AngularJS promise/then 与递归函数一起使用。但是 then 函数没有被调用(错误、成功、通知回调都没有被调用)。
Here is my code:
这是我的代码:
recursive function
递归函数
loadSection2 = function() {
var apiURL = "http://..."
var deferred = $q.defer();
$http({
method: "GET",
url: apiURL
}).success(function(result, status, headers, config) {
console.log(result);
loadCount++;
if(loadCount < 10) {
newSectionArray.push(result);
loadSection2();
} else {
loadCount = 0;
deferred.resolve();
return deferred.promise;
}
}).error(function() {
return deferred.reject();
});
deferred.notify();
return deferred.promise;
};
then
然后
loadSection2().then(function() {
console.log("NEW SECTIONS LOADED, start adding to document");
addContent();
}, function() {
console.log("ERROR CALLBACK");
}, function() {
console.log("NOTIFY CALLBACK");
}).then(function() {
loadScrollActive = false;
});
I think, the then has to get the first notify-callback at least. But there is no callback. Is then not working with recursive function?
我认为,那么至少必须获得第一个通知回调。但是没有回调。那么不使用递归函数吗?
回答by Mathew Berg
EDIT - 11/11/2015There is a much cleaner way if you don't care about notify:
编辑 - 2015 年 11 月 11 日,如果您不关心通知,则有一种更清洁的方法:
loadSection2 = function (){
var apiURL = "http://..."
return $http.get(apiURL)
.then(function(response){
loadCount++;
if (loadCount < 10) {
newSectionArray.push(response.data);
return loadSection2();
}
loadCount = 0;
});
};
Old answer available here:
旧答案可在此处获得:
You could continuously pass the promise all the way through.
你可以一直通过这个承诺。
loadSection2 = function(deferred) {
if(!deferred){
deferred = $q.defer();
}
var apiURL = "http://..."
$http({
method: "GET",
url: apiURL
}).success(function(result, status, headers, config) {
console.log(result);
loadCount++;
if(loadCount < 10) {
newSectionArray.push(result);
loadSection2(deferred);
} else {
loadCount = 0;
deferred.resolve();
return deferred.promise;
}
}).error(function() {
return deferred.reject();
});
deferred.notify();
return deferred.promise;
};
回答by VitalyB
I wanted to make a solution that doesn't pass "deferred" variable around and even though I wouldn't say it is a better approach, it works and I learned a from it (jsfiddle).
我想制定一个不传递“延迟”变量的解决方案,尽管我不会说这是一种更好的方法,但它确实有效,而且我从中学到了(jsfiddle)。
19/Aug/14- Updated the code to a much shorter version by removing the creation of another promise in f1(). I hope that it is clear how it relates to the original question. If it isn't let me know in a comment.
2014 年 8 月 19 日- 通过删除 f1() 中另一个承诺的创建,将代码更新为更短的版本。我希望它与原始问题的关系很清楚。如果不是在评论中让我知道。
f1().then(function() {
console.log("done");
});
function f1(counter) {
if (!counter) {
counter = 0;
}
counter++;
console.log(counter);
return asyncFunc().then(function() {
if (counter < 10) {
return f1(counter);
} else {
return;
}
});
}
function asyncFunc() {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve();
}, 100);
return deferred.promise;
}
回答by Beetroot-Beetroot
Fauphi,
福菲,
Recursion is totally viable but not a particularly "promisy" approach.
递归是完全可行的,但不是一种特别“有前途”的方法。
Given that you have deferreds/promises available, you can dynamically build a .then()chain, which delivers a promise of a populated array.
鉴于您有可用的延迟/承诺,您可以动态构建一个.then()链,它提供填充数组的承诺。
function loadSection2(arr) {
return $http({
method: "GET",
url: "http://..."
}).then(function(result, status, headers, config) {
console.log(result);
arr.push(result);
return arr;//make the array available to the next call to loadSection2().
}, function() {
console.log("GET error");
return $q.defer().resolve(arr).promise;//allow the chain to continue, despite the error.
//or I think $q's .then() allows the much simpler form ...
//return arr; //allow the chain to continue, despite the error.
});
};
var newSectionPromise = $q.defer().resolve([]).promise;//note that the deferred is resolved with an anonymous new array.
//Now we build a .then() chain, ten long, ...
for (var i=0; i<10; i++) {
newSectionPromise = newSectionPromise.then(loadSection2);
}
// ... and do something with the populated array when the GETs have done their thing.
newSectionPromise().then(function(arr) {
console.log(arr.length + " new sections loaded, start adding to document");
addContent(arr);
}, function() {
console.log("ERROR CALLBACK");
}).then(function() {
loadScrollActive = false;
});
untested
未经测试
What was newSectionArrayis now created anonymously and passed down the .then()chain regardless of success/failure of the individual GETs, emerging as arrin the final .then's success handler, where it is passed to addContent(). This avoids the need for member newSectionArrayin the outer scope.
什么是newSectionArray现匿名的创建和流传下来的.then(),无论成功的连锁/个人的失败入眼,如出现arr在最后。后来的成功处理程序,在那里它被传递给addContent()。这避免了newSectionArray在外部作用域中需要成员。
Rearranging slightly, loadSection2could be made anonymous, further reducing the number of members added to the outer scope.
稍微重新排列,loadSection2可以匿名,进一步减少添加到外部范围的成员数量。
The need for an explicit notification disappears as :
对显式通知的需求消失为:
- there is no longer a master deferred to be notified
console.log(result);in the GET success handler provides all the notification necessary.
- 不再有推迟通知的主人
console.log(result);在 GET 成功处理程序中提供了所有必要的通知。

