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 newSectionArray
is now created anonymously and passed down the .then()
chain regardless of success/failure of the individual GETs, emerging as arr
in the final .then's success handler, where it is passed to addContent()
. This avoids the need for member newSectionArray
in the outer scope.
什么是newSectionArray
现匿名的创建和流传下来的.then()
,无论成功的连锁/个人的失败入眼,如出现arr
在最后。后来的成功处理程序,在那里它被传递给addContent()
。这避免了newSectionArray
在外部作用域中需要成员。
Rearranging slightly, loadSection2
could 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 成功处理程序中提供了所有必要的通知。