正确引用延迟的AJAX调用中的变量

时间:2015-01-28 02:54:24

标签: javascript jquery ajax

我有一个函数fetchAlbum,用于设置占位符,发出AJAX请求,并在成功时重新访问其占位符以进行更新。它看起来像这样:

function fetchAlbum() {
    albumCounter++;
    var albumElement = $('<div/>', { id: 'albumplaceholder-' + albumCounter }).html('Loading...').appendTo('#results');

    var callbackID = '#albumplaceholder-' + albumCounter;

    imgurJSON = $.ajax({
         //...
         success : function() {
             $(callbackID).html(imgurJSON.responseJSON.data //...);
         }
     });
 }

这一切都有效,但是如果重复调用此函数,则会遇到问题。 AJAX请求的success函数似乎总是引用最新的callbackID而不是预期的。{/ p>

因此,当创建3个占位符并且ajax结果进入时,它们都引用#albumplaceholder-3而不是它们各自的。{/ p>

如何解决这个问题?提前谢谢。

修改:感谢您的建议,但我最终解决了这样的问题:

我不是每次都调用fetchAlbum()函数,而是设置这样的元素:

<div class="image-album" data-albumid="IMGURID"></div>

最后使用$('.image-album).each(function(){ ... }),分别浏览每个占位符,读取data-albumid属性,发出AJAX请求等等。这样可以保持正确的闭合。

3 个答案:

答案 0 :(得分:1)

恭喜你,你被closure感到难过!这使您成为下一级JavaScript开发人员。这需要一杯咖啡(它甚至还没有午夜)。

闭包是当一个函数在另一个函数内部时,内部函数使用外部函数中的变量。在您的情况下,AJAX成功处理程序使用albumCounter

albumCounter只有一个值。你没有制作三份副本 - 每份都有自己的连续值 - 就像你期望的那样。当ajax调用回来时,他们都在查看对值的一个引用,而不是它们自己的单个副本。您应该albumCounter使用自己的参数,例如albumId,就像其他答案中所建议的那样。

您可以像这样重现行为:

var i = 0;
function outerFunction(){
  i++;
  function innerFunction(){
    setTimeout(function(){
      console.log(i);
    }, 5000);
  };
  innerFunction(); //execute the inner function
}

outerFunction();
outerFunction();
outerFunction(); //in 5 seconds, logs the number 3, 3 times

相反,做这样的事情:

 function outerFunction(iterator){
   function innerFunction(){
     setTimeout(function(){
       console.log(iterator);
     }, 5000);
  };
  innerFunction(); //execute the inner function
}
 for(var i = 0; i < 3; i++){
   outerFunction(i); //logs 1, 2, 3 in 5 seconds
}

或者在你的情况下

function fetchAlbum(albumCounter) { //the outer function

  var albumElement = $('<div/>', { id: 'albumplaceholder-' + albumCounter }).html('Loading...').appendTo('#results');

  var callbackID = '#albumplaceholder-' + albumCounter;

  imgurJSON = $.ajax({ //execute the inner function
     //...
     success : function() { //the inner function
         $(callbackID).html(imgurJSON.responseJSON.data //...);
     }
  });
}

fetchAlbum(1);
fetchAlbum(2); // In other words, something outside of `fetchAlbum()`
fetchAlbum(3); // should oversee which album to fetch.

答案 1 :(得分:0)

使用albumID作为callbackID的前缀,也可以使其独一无二并解决您的问题。

var callbackID = '#albumplaceholder-' + albumCounter + "-" + albumID;

var albumElement = $('<div/>', { id: callbackID }).html('Loading...').appendTo('#results');

您还可以添加时间戳,使其更加独特。

但我会建议您依赖ajax响应,只需使用albumID返回响应并按此处理

success : function(res) {
         var id = res.id// {id : albumID}
         $(id).html(imgurJSON.responseJSON.data //...);

您明白了,您需要相应地修改var callbackID

答案 2 :(得分:0)

尝试更改,

albumCounter++;
var albumElement = $('<div/>', { id: 'albumplaceholder-' + albumCounter}).html('Loading...').appendTo('#results');

var callbackID = '#albumplaceholder-' + albumCounter;

    albumCounter++;

    var callbackID = '#albumplaceholder-' + albumCounter;

    var albumElement = $(callbackID).html('Loading...').appendTo('#results');