代码之家  ›  专栏  ›  技术社区  ›  Matt Anxo P

在$.getjson函数期间设置的变量只能在函数内访问

  •  42
  • Matt Anxo P  · 技术社区  · 15 年前

    这可能更像是一个范围界定问题。我试图在$.getjson函数中设置一个JSON对象,但我需要能够在回调之外使用该对象。

    var jsonIssues = {};  // declare json variable
    
    $.getJSON("url", function(data) {
        jsonIssues = data.Issues;
    });
    
    // jsonIssues not accessible here
    

    在另一篇文章中也提出了类似的问题,大家一致认为,我需要对JSON对象做的任何事情都需要在回调函数中完成,并且不能在其他任何地方访问。我真的无法继续访问/操作$.getjson回调之外的json对象吗?返回变量或设置全局变量怎么样?

    我很感谢你的帮助。这似乎不对…

    更新:

    尝试将$.Ajax()异步设置设置为false,并运行相同的代码,但没有成功。我尝试的代码如下:

    var jsonIssues = {};  // declare json variable
    
    $.ajax({ async: false });
    
    $.getJSON("url", function(data) {
        jsonIssues = data.Issues;
    });
    
    // jsonIssues still not accessible here
    

    另外,我有几个响应,全局变量应该可以正常工作。我应该澄清一下,所有这些代码都在 $(document).ready(function() { . 要设置全局变量,我应该在document.ready之前声明它吗?像这样的:

    var jsonIssues = {};
    
    $(document).ready(function() {
    
      var jsonIssues = {};  // declare json variable
    
      $.getJSON("url", function(data) {
          jsonIssues = data.Issues;
      });
    
      // now accessible?
    }
    

    我觉得document.ready中声明的变量应该在document.ready的任何部分“全局”可访问和修改,包括$getjson回调函数等子函数。我可能需要阅读有关javascript变量范围的内容,但似乎要实现我要实现的目标并不容易。谢谢你的回复。

    更新第2号: 根据对下面答案的评论,我确实使用了$.Ajax 而不是 得到了我想要的结果。代码如下:

    var jsonIssues = {};
        $.ajax({
            url: "url",
            async: false,
            dataType: 'json',
            success: function(data) {
                jsonIssues = data.Issues;
            }
        });
    
        // jsonIssues accessible here -- good!!
    

    对我的答案发表后续评论(我非常感谢)。我这样做的目的是首先加载一个JSON对象,其中包含一系列问题,然后用户可以将这些问题从中删除并保存下来。但这是通过页面上的后续交互完成的,我无法预知用户将要对JSON对象做什么。 在内部 回调。因此,需要在回调完成后使其可访问。这里有人看到我的逻辑有缺陷吗?说真的,因为我可能看不到…

    另外,我正在阅读.ajax()jquery文档,它说将async设置为false“会同步加载数据。在请求处于活动状态时阻止浏览器。当需要同步时,最好通过其他方式阻止用户交互。”

    有人知道我应该如何阻止用户交互吗?为什么这么担心?再次感谢您的回复。

    6 回复  |  直到 11 年前
        1
  •  34
  •   strager    15 年前

    $.getJSON 是异步的。也就是说,执行调用后的代码 盖特森 获取并分析数据并调用回调。

    因此,考虑到这一点:

    a();
    
    $.getJSON("url", function() {
        b();
    });
    
    c();
    

    呼叫的顺序 a , b c 也许是 a b c 什么 想要,在这种情况下)或 a c b (更可能发生)。

    解决方案?

    同步XHR请求

    使请求同步而不是异步:

    a();
    
    $.ajax({
        async: false,
        url: "url",
        success: function() {
            b();
        }
    });
    
    c();
    

    重组代码

    将呼叫转移到 C 在接到电话后 :

    a();
    
    $.getJSON("url", function() {
        b();
    
        c();
    });
    
        2
  •  9
  •   Dave Ward    15 年前

    记住,当您提供回调函数时,重点是将回调的执行推迟到稍后,然后立即继续执行下一个回调函数。这是必要的,因为浏览器中的Javascript是单线程执行模型。强制同步执行是可能的,但它会在整个操作期间挂起浏览器。对于类似于$.getjson的情况,浏览器停止响应的时间非常长。

    换句话说,你试图找到一种使用这种程序范式的方法:

    var foo = {};
    
    $.getJSON("url", function(data) {
      foo = data.property;
    });
    
    // Use foo here.
    

    当需要重构代码以使其更像这样流动时:

    $.getJSON("url", function(data) {
      // Do something with data.property here.
    });
    

    如果您希望保持回调函数的简单性,“do something”可能是对另一个函数的调用。重要的一点是,在执行代码之前,您要等到$.getjson完成。

    您甚至可以使用自定义事件,以便您在$.getjson订阅issuesReceived事件之后放置的代码,并在$.getjson回调中引发该事件:

    $(document).ready(function() {
      $(document).bind('IssuesReceived', IssuesReceived)
    
      $.getJSON("url", function(data) {
        $(document).trigger('IssuesReceived', data);
      });
    });
    
    function IssuesReceived(evt, data) {
      // Do something with data here.
    }
    

    更新:

    或者,您可以全局存储数据,并只使用自定义事件通知数据已被接收和全局变量已更新。

    $(document).ready(function() {
      $(document).bind('IssuesReceived', IssuesReceived)
    
      $.getJSON("url", function(data) {
        // I prefer the window.data syntax so that it's obvious
        //  that the variable is global.
        window.data = data;
    
        $(document).trigger('IssuesReceived');
      });
    });
    
    function IssuesReceived(evt) {
      // Do something with window.data here.
      //  (e.g. create the drag 'n drop interface)
    }
    
    // Wired up as the "drop" callback handler on 
    //  your drag 'n drop UI.
    function OnDrop(evt) {
      // Modify window.data accordingly.
    }
    
    // Maybe wired up as the click handler for a
    //  "Save changes" button.
    function SaveChanges() {
      $.post("SaveUrl", window.data);
    }
    

    更新2:

    对此作出回应:

    有人知道我应该如何阻止用户交互吗?为什么这么担心?再次感谢您的回复。

    应该避免使用同步Ajax调用阻塞浏览器的原因是 被阻止的javascript线程也会阻止浏览器中的其他所有内容。 包括其他选项卡甚至其他窗口。这意味着没有滚动,没有导航,没有任何东西。出于所有的意图和目的,似乎浏览器崩溃了。正如您所能想象的,一个以这种方式运行的页面是 重要的 给用户带来麻烦。

        3
  •  5
  •   Alexander    13 年前

    也许这工作对我有用……:)

    $variable= new array();
    
    $.getJSON("url", function(data){
    asignVariable(data);
    }
    
    function asignVariable(data){
    $variable = data;
    }
    
    console.log($variable);
    

    希望它能帮助你…… :)

        4
  •  4
  •   Björn Roberg    11 年前

    你可以承诺:

    var jsonPromise = $.getJSON("url")
    
    jsonPromise.done(function(data) {
        // success
        // do stuff with data
    });
    
    jsonPromise.fail(function(reason) {
        // it failed... handle it
    });
    
    // other stuff ....
    
    jsonPromise.then(function(data) {
        // do moar stuff with data
        // will perhaps fire instantly, since the deferred may already be resolved.
    });
    

    这是一个非常直截了当的可行方法,可以让异步代码感觉更为必要。

        5
  •  1
  •   Nosredna    15 年前

    但这是通过页面上的后续交互来完成的,我无法预见用户将要对回调中的JSON对象做什么。

    回调是为用户与数据交互设置屏幕的机会。

    您可以为用户创建或显示HTML,并设置更多回调。

    大多数情况下,您的代码都不会运行。编写一个Ajax页面的所有内容都是考虑在什么时候可能发生哪些事件。

    这是因为它是“ajax”而不是“sjax”。这是因为它很难从异步转换为同步。预计您将执行页面异步操作。

    事件驱动的编程一开始可能会令人沮丧。

    我已经在JS中完成了计算密集型的财务算法。即便如此,这也是一样的——你把它分成几个小部分,然后事件就超时了。

    javascript中的动画也是事件驱动的。实际上,除非脚本反复放弃控制权,否则浏览器甚至不会显示移动。

        6
  •  -3
  •   Community rohancragg    7 年前

    你只是碰到了范围问题。

    简短回答:

    window.jsonIssues = {};  // or tack on to some other accessible var
    
    $.getJSON("url", function(data) {
        window.jsonIssues = data.Issues;
    });
    
    // see results here
    alert(window.jsonIssues);
    

    长回答:

    Scoping issue in Javascript Javascript closure scoping issue