$ .getJSON在for循环中调用行为不端

时间:2012-04-23 20:14:57

标签: javascript json flickr

以下是对我的问题的描述:

我有一个包含某些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请求!谢谢大家!

3 个答案:

答案 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]);
}