JQuery - 将ajax响应存储到全局变量中

71

我在jQuery和ajax领域还是新手,但我有一个$.ajax请求执行GET操作以检索一些XML文件(大小约为6KB或更小)。然而,在用户停留在该页面的时间内,XML内容不应/不会更改(这个设计我无法更改,我也无法更改XML文件,因为它来自其他地方)。因此,我有一个全局变量,将响应数据存储在其中,并且对数据进行任何后续查找都是在此变量上执行的,这样就不需要进行多次请求。

考虑到XML文件可能会增加,我不确定这是否是最佳实践,而且出于Java背景的考虑,我的想法是全局公共变量通常是不可取的。

因此,我的问题是是否有更好的方法来解决这个问题,以及如果文件扩展到一些荒谬的文件大小是否会导致任何内存问题?

我认为数据可以传递给xml对象内部的某些getter/setter类型函数,这将解决我的全局公共变量问题,但仍然引出了一个问题,即是否应将响应存储在对象本身中。

例如,我目前所做的是:

// top of code
var xml;
// get the file
$.ajax({
  type: "GET",
  url: "test.xml",
  dataType: "xml",
  success : function(data) {
    xml = data;
  }
});
// at a later stage do something with the 'xml' object
var foo = $(xml).find('something').attr('somethingElse');

10
警告给勇敢的探险家们。下面的许多解决方案使用了async:false。这里存在危险。 - Luke Schafer
16个回答

73

这里有一个做得很好的函数。我没能让上面的最佳答案工作。

jQuery.extend({
    getValues: function(url) {
        var result = null;
        $.ajax({
            url: url,
            type: 'get',
            dataType: 'xml',
            async: false,
            success: function(data) {
                result = data;
            }
        });
       return result;
    }
});

然后要访问它,可以这样创建变量:

var results = $.getValues("url string");

3
实际上只需添加“async: false”就能解决你在处理这个问题时遇到的很多问题。 - Rooster
6
可以造成很多问题,比如让浏览器冻结几秒钟 :) - Armen Markossyan
异步操作会引起很多问题。有什么方法可以解决异步问题? - Maciek Semik
4
此代码在Chrome控制台上发出警告,内容为Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/. - RN Kushwaha
@ArmenMarkossyan 这个有更好的替代方案吗?为什么它会引起很多问题? - Zypps987
显示剩余4条评论

36

这对我有用:

var jqxhr = $.ajax({
    type: 'POST',       
    url: "processMe.php",
    data: queryParams,
    dataType: 'html',
    context: document.body,
    global: false,
    async:false,
    success: function(data) {
        return data;
    }
}).responseText;

alert(jqxhr);
// or...
return jqxhr;

需要注意的是:global: falseasync: false,最后还有将 responseText 链接到 $.ajax 请求上。


2
async:false会造成混乱!如果你有一个带有loading gif或其他东西的beforeSend,async将使它非常丑陋。 - Maciek Semik
这对我来说非常有效。我一直在为将Ajax响应存储到全局变量中而苦苦挣扎,该死的。 - King

35

只有存储才能解决这个问题。使用内存分页应该能减少潜在的问题。

我建议不要使用名为“xml”的全局变量,而是像这样做:

var dataStore = (function(){
    var xml;

    $.ajax({
      type: "GET",
      url: "test.xml",
      dataType: "xml",
      success : function(data) {
                    xml = data;
                }
    });

    return {getXml : function()
    {
        if (xml) return xml;
        // else show some error that it isn't loaded yet;
    }};
})();

然后使用以下方式访问:

$(dataStore.getXml()).find('something').attr('somethingElse');

9
【警告】此答案无效,请阅读下面的rfc1484的答案。 - skozz
1
可能是因为漏掉了$()。 - Luke Schafer
1
我同意 @skozz 的观点,它不起作用。它返回未定义。唯一的解决方法似乎是将 async 设为 false - John R Perry

22

你不必做这一切。我在我的项目中遇到了同样的问题。你需要在成功回调函数内部进行函数调用,以重置全局变量。只要你将异步 JavaScript 设置为 false,它就能正常工作。下面是我的代码,希望对你有所帮助。

var exists;

//function to call inside ajax callback 
function set_exists(x){
    exists = x;
}

$.ajax({
    url: "check_entity_name.php",
    type: "POST",
    async: false, // set to false so order of operations is correct
    data: {entity_name : entity},
    success: function(data){
        if(data == true){
            set_exists(true);
        }
        else{
            set_exists(false);
        }
    }
});
if(exists == true){
    return true;
}
else{
    return false;
}

希望这能对你有所帮助。


1
为我提供神一般的答案 :D - Aditzu
1
这个工作得相当不错!只有一件事,如果(data == true)需要更改。它可能是空的。 - Maciek Semik
我试图从响应的ajax中重新创建节点。每当我使用现有节点时,我的脚本都能正常工作,但是在尝试从ajax响应中重建对象结构时却不起作用。这个解决方案对我起了作用。我现在不会探索它,但我怀疑异步设置使得差异。 - IberoMedia
这对我的项目非常有效。我只使用了函数调用,不需要真假的东西。 - user1794918

10

你可能会发现将响应值存储在DOM元素中更容易,因为它们可以全局访问:

<input type="hidden" id="your-hidden-control" value="replace-me" />

<script>
    $.getJSON( '/uri/', function( data ) {
        $('#your-hidden-control').val( data );
    } );
</script>

这种方法的优点是不需要将“async”设置为false。显然,这是否合适取决于您试图实现什么。


2
太简单了!虽然我使用了jQuery的.data()方法来存储JSON,而不是设置输入值,但它对我起作用了。 - Anthony
1
某些应用的逻辑解决方案非常干净。建议:在取消操作的情况下,最好重置“your-hidden-control”的“value”。 - Robert

8
你的问题可能与本地或全局范围无关,只与“成功”函数执行和你尝试从变量中取出数据的时间之间的服务器延迟有关。很有可能是在ajax“成功”函数触发之前就尝试打印变量内容了。

7
        function getJson(url) {
            return JSON.parse($.ajax({
                type: 'GET',
                url: url,
                dataType: 'json',
                global: false,
                async: false,
                success: function (data) {
                    return data;
                }
            }).responseText);
        }

        var myJsonObj = getJson('/api/current');

这个有效!!!


4

在"document.ready"事件阶段,我一直很苦恼如何将jQuery ajax的结果传递给我的变量。

当页面加载完成后,当用户触发下拉框的“onchange”事件时,jQuery的ajax会加载到我的变量中,但是当页面首次加载时,数据就无法填充到变量中。

我尝试了许多不同的方法,但最终,Charles Guilbert的方法对我来说效果最好。

向Charles Guilbert致敬!使用他的答案,我可以在页面首次加载时将数据传递给我的变量。

以下是可工作脚本的示例:

    jQuery.extend
    (
        {
            getValues: function(url) 
            {
                var result = null;
                $.ajax(
                    {
                        url: url,
                        type: 'get',
                        dataType: 'html',
                        async: false,
                        cache: false,
                        success: function(data) 
                        {
                            result = data;
                        }
                    }
                );
               return result;
            }
        }
    );

    // Option List 1, when "Cats" is selected elsewhere
    optList1_Cats += $.getValues("/MyData.aspx?iListNum=1&sVal=cats");

    // Option List 1, when "Dogs" is selected elsewhere
    optList1_Dogs += $.getValues("/MyData.aspx?iListNum=1&sVal=dogs");

    // Option List 2, when "Cats" is selected elsewhere
    optList2_Cats += $.getValues("/MyData.aspx?iListNum=2&sVal=cats");

    // Option List 2, when "Dogs" is selected elsewhere
    optList2_Dogs += $.getValues("/MyData.aspx?iListNum=2&sVal=dogs");

3
     function get(a){
            bodyContent = $.ajax({
                  url: "/rpc.php",
                  global: false,
                  type: "POST",
                  data: a,
                  dataType: "html",
                  async:false
               } 
            ).responseText;
            return bodyContent;

  }

2

我也遇到了这个问题。有很多答案,但只有一个简单而正确的答案,我会提供给你。关键是使你的$.ajax调用同步!

$.ajax({  
    async: false, ...

2
谢谢你的降级,但是嘿,我来这里是寻找一个没有阻塞操作的解决方案,对于其他可能遇到这个问题的人来说,我的解决方案可能就是答案! - stvn
2
每个人都在这个问题上进行死帖,所以我也不妨这样做。从jQuery 1.8开始,async: false已被弃用,总有比同步请求更好的处理代码的方法。 - Andrew Larsson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接