以下是对我的问题的描述:
我有一个包含某些flickr照片的ID的数组。 对于每个id,我需要制作两个嵌套的apiCalls(一个用于flickr photosets api,一个用于photoinfo api)并在我的页面中添加一些html
结构是:
for(var i=0; i<ARRAY_ID.length; i++){
$.getJSON(apiCall, function(data) {
// some processing here
$.getJSON(apiCall2,function(data){
//other processing here
每个&#34; apiCall&#34;是一个字符串,包含对photosets api(apiCall)的正确调用,然后是photoInfo api(apiCall2)
在所有这些处理之后,在&#34; apiCall2&#34;阻止,我将一些html附加到div(这导致与ARRAY_ID长度一样多的块元素)。
我有奇怪的行为:所有附加的块元素都包含相同的文本,图片和链接。它以预期的数量打印出来,但内容与所有内容相同。我猜它是for循环而不是等待$ .getJSON完成。我怎样才能实现这一目标?我严格要求在处理下一个json请求之前完成每个json请求!谢谢大家!
答案 0 :(得分:4)
你似乎有2个不同但相关的问题。
所有附加的块元素包含相同的文本,图片和链接。它以预期的数字打印出来,但内容与所有内容相同。
如果您在回调中引用了i
,则需要将其包含在for
中。否则,$.getJSON
是异步的,for
将在调用回调之前完成,i
将始终是循环中的最后一个值 - ARRAY_ID.length
:
for(var i = 0; i < ARRAY_ID.length; i++) {
(function (i) {
// work with the local `i` rather than the shared `i` from the loop
})(i);
}
我猜是for循环没有等待$ .getJSON完成。我怎样才能实现这一目标?我严格要求在处理下一个json请求之前完成每个json请求!
您无法for
到&#34;等待&#34;每组$.getJSON
完成。但是,您可以使用for
循环和闭包构建queue,等待明确告诉next
继续:
var focus = $(...); // either match an existing element or create one: '<div />'
for(var i = 0; i < ARRAY_ID.length; i++) {
(function (i) {
focus.queue('apicalls', function (next) {
$.getJSON(apiCall, function(data) {
// some processing here
$.getJSON(apiCall2,function(data){
//other processing here
next(); // start the next set of api calls
});
});
});
})(i);
}
focus.dequeue('apicalls');
答案 1 :(得分:1)
这是闭包的常见问题。你的回调是从包含for循环的函数的上下文继承变量(我将它称为main函数)。试试这个:
for(var i=0; i<ARRAY_ID.length; i++){
$.getJSON(apiCall, (function(i, v1, v2, etc) { return function(data) {
// some processing here
$.getJSON(apiCall2,function(data){
//other processing here
})(i, v2, v3, etc));
}
基本上,现在您正在更改闭包从中访问变量的上下文。您创建一个匿名函数并传递您从主函数访问的所有变量。在示例中,我传递变量i,v1,v2等表示您可能正在访问的其他变量。
通过为每个闭包调用创建正确的上下文,您应该能够解决此问题。
答案 2 :(得分:1)
很可能是范围问题。
如果您的回调传递给getJSON方法,请使用循环的i
变量,那么它们很可能都使用i
的最后一个值结束。
解决方案是
function handleJsonRequests(index,id){
// use index instead of i
// use id instead of ARRAY_ID[i]
$.getJSON(apiCall, function(data) {
// some processing here
$.getJSON(apiCall2,function(data){
//other processing here
}// end of function
for(var i=0; i<ARRAY_ID.length; i++){
handleJsonRequests(i, ARRAY_ID[i]);
}