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

Referencing a variable in a delayed AJAX call correctly

本文关键字:变量 调用 AJAX 引用 延迟      更新时间:2023-09-26

我有一个函数,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,而不是预期的。

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

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

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

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

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

并在最后使用$('.image-album).each(function(){ ... }),分别遍历每个占位符,读取data-albumid属性,发出AJAX请求等等。这将保持正确的闭包。

恭喜你,你被关闭难住了!这将使您进入下一个级别的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.

尝试更改,

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');

使用 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