【问题标题】:Using variable outside of ajax callback function在ajax回调函数之外使用变量
【发布时间】:2010-11-29 20:30:33
【问题描述】:

在回调函数之外使用全局变量的最佳方法是什么?

    var icon; 
    $(function(){

      $.get('data.xml', function(xml){

           icon = xml.documentElement.getElementsByTagName("icon");
           //this outputs a value
           console.log(icon);
       });
       //this is null
       //How can this maintain the value set above?
       console.log(icon);
    });

【问题讨论】:

  • 你要归档什么?
  • 它如何保持什么价值?你需要更清楚。
  • 没有最好的方式来使用它们
  • 它只需要保存xml元素的值。
  • 这个问题已经被问了一百万次了。由于 $.get 是异步的,因此传递给它的函数不会立即执行。因此,在调用 $.get 后调用 console.log 时,尚未调用回调。这就是为什么添加足够长的超时会起作用(但会是一个非常讨厌的黑客)

标签: javascript jquery ajax


【解决方案1】:

您提供的代码完全有效——事实上,icon 确实“维护”了它的价值。问题很可能是get() 异步运行——仅在从服务器完全加载'data.xml' 之后调用匿名函数。所以现实世界的执行顺序是这样的:

  1. 调用get('data.xml', function(xml){...})(开始加载data.xml)
  2. 调用console.log(icon)(此时icon仍为空)
  3. (data.xml 完成加载)现在调用匿名函数,将值分配给图标:icon = xml.documentElement.getElementsByTagName("icon")

如果你想用icon 的值做一些事情,'data.xml'被获取之后,那么你需要在里面 匿名回调函数。像这样:

var icon; 
$(function(){

  $.get('data.xml', function(xml){
       icon = xml.documentElement.getElementsByTagName("icon");
       console.log(icon);
   });
});

祝你好运!


注意:您仍然可以在 匿名函数之外的代码中使用 icon,但您需要等待,直到 匿名函数之后才能访问它功能已运行。最好的方法是将依赖代码放入自己的函数中,然后从回调函数中调用该函数:

var icon; 
$(function(){

  $.get('data.xml', function(xml){
       icon = xml.documentElement.getElementsByTagName("icon");
       loadIcon();
   });

   function loadIcon() {
       console.log(icon);
       // ... do whatever you need to do with icon here
   }
});

【讨论】:

  • 我试图避免您的第二种解决方案。但看起来这是唯一的出路。更糟糕的是,我必须添加一个 setTimeout 函数才能使其正常工作。啊!
  • @Mike,如果您要发布更多关于您正在做什么的信息(或者可能会提出另一个问题),我们可以帮助您避免使用计时器。 (让我们帮助您避免这种情况——这里几乎肯定不需要计时器)。
  • @Mike:您的问题是由于在您调用 addMarkers() 函数时谷歌地图没有完全初始化。如他们的tutorial 所示,谷歌希望在窗口(或正文)加载事件中创建 Map 对象——否则会产生“奇怪的行为”。您对 jQuery $(function(){...}) 的使用将您的初始化绑定到 DOM 加载事件,该事件发生在窗口/正文加载事件之前。创建一个新的 S.O.问题,(在这里发布一个链接,以便我看到它),我会帮助你解决它。
  • @Mike:查看ready() 的 jQuery 文档。另请查看Events Section of the Google Maps v3 API docs - 滚动到底部,它显示了一种 google 提供的方法来挂钩窗口加载事件,并调用您的初始化函数:google.maps.event.addDomListener(window, 'load', initialize); 这种方法应该 co- jQuery 的各种事件挂钩机制可以接受。
  • 如果我将代码放在正文加载事件中并摆脱文档就绪功能,似乎一切正常。将是查看文档就绪与正文负载与窗口负载的好时机。谢谢
【解决方案2】:

console.log(icon); 在您执行异步 ajax 时此时不会有值。在回调函数或它调用的函数中移动处理响应的整个代码。

$(function(){

  $.get('data.xml', function(xml) {
       var icon = xml.documentElement.getElementsByTagName("icon");
       console.log(icon);
   });
});

【讨论】:

  • 我需要在回调函数之外使用变量。
  • @Mike,你不能在回调函数之外使用它。您可以重构代码,以便回调函数依次调用您编写的自定义函数。或者您可以将自定义代码直接放入回调函数中。但是没有办法在ajax调用之后直接使用它,因为这里大家一直在说它是异步的(可以使调用同步但这是一个非常糟糕的主意,因为同步ajax会锁定浏览器)。
【解决方案3】:

问题是$.get正在排队一个请求,但是没有同步执行请求;它立即返回。 JavaScript 不是多线程的!

你必须在回调函数中执行console.log(icon) inside。在执行该行时,AJAX 调用尚未完成。

全局icon 变量从回调中设置;您的代码在这方面是正确的。

【讨论】:

    【解决方案4】:

    这样可以帮助可视化代码。

        var icon; 
        $(function(){
            $.get('data.xml', callback); // sends ajax request
            // next line happens immediately unless ajax request is set to synchronous
            console.log(icon); // logs undefined
        });
        function callback(xml){ // onsuccess callback happens
            icon = xml.documentElement.getElementsByTagName("icon");
            console.log(icon); // logs Array
        }
    

    我删除了匿名函数并将回调放在console.log 之后。就像其他人指出的,ajax 回调异步发生,而 javascript 继续执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多