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

Javascript $.getJSON函数期间设置的变量只能在函数内访问,javascript,jquery,variables,scope,callback,Javascript,Jquery,Variables,Scope,Callback,这可能更像是一个范围问题。我试图在$.getJSON函数中设置一个JSON对象,但我需要能够在回调之外使用该对象 var jsonIssues = {}; // declare json variable $.getJSON("url", function(data) { jsonIssues = data.Issues; }); // jsonIssues not accessible here 在另一篇文章中也提出了类似的问题,大家一致认为,我需要对JSON对象执行的任何操作

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

var jsonIssues = {};  // declare json variable

$.getJSON("url", function(data) {
    jsonIssues = data.Issues;
});

// jsonIssues not accessible here
在另一篇文章中也提出了类似的问题,大家一致认为,我需要对JSON对象执行的任何操作都需要在回调函数中完成,并且不能在其他任何地方访问。是否真的没有办法在$.getJSON回调之外继续访问/操作该JSON对象?返回变量或设置全局变量怎么样

我非常感谢你的帮助。这似乎不对

更新:

window.jsonIssues = {};  // or tack on to some other accessible var

$.getJSON("url", function(data) {
    window.jsonIssues = data.Issues;
});

// see results here
alert(window.jsonIssues);
尝试将$.ajax()异步设置设置设置为false,并运行相同的代码,但没有成功。我试过的代码如下:

var jsonIssues = {};  // declare json variable

$.ajax({ async: false });

$.getJSON("url", function(data) {
    jsonIssues = data.Issues;
});

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

    // jsonIssues accessible here -- good!!
另外,我得到了一些回答,一个全局变量应该可以正常工作。我应该澄清,所有这些代码都在
$(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而不是.getJSON,并实现了我想要的结果。代码如下:

var jsonIssues = {};  // declare json variable

$.ajax({ async: false });

$.getJSON("url", function(data) {
    jsonIssues = data.Issues;
});

// jsonIssues still not accessible here
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“同步加载数据。在请求处于活动状态时阻止浏览器。在需要同步时,最好通过其他方式阻止用户交互。”


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

$。getJSON
是异步的。也就是说,调用后的代码是在执行时执行的。
$。getJSON
获取和解析数据并调用回调

var jsonIssues = {};  // declare json variable

$.getJSON("url", function(data) {
    jsonIssues = data.Issues;
});

// jsonIssues not accessible here
因此,鉴于此:

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();
重组代码 在调用
b
后,将调用移动到
c

a();

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

    c();
});

您只是遇到了范围界定问题

简短回答:

window.jsonIssues = {};  // or tack on to some other accessible var

$.getJSON("url", function(data) {
    window.jsonIssues = data.Issues;
});

// see results here
alert(window.jsonIssues);
长答案:

window.jsonIssues = {};  // or tack on to some other accessible var

$.getJSON("url", function(data) {
    window.jsonIssues = data.Issues;
});

// see results here
alert(window.jsonIssues);

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

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

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

大多数情况下,您的代码都不会运行。编写Ajax页面的全部内容都是考虑何时可能发生哪些事件

这是因为它是“Ajax”而不是“Sjax”。这是因为从异步更改为同步是一件痛苦的事情。您应该异步完成页面

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

我在JS中做过计算密集型的金融算法。即使如此,也是一样的——你把它分成几个小部分,事件就是超时


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

请记住,当您提供回调函数时,其要点是将回调的执行推迟到以后,并立即继续执行下一个。这是nec由于浏览器中的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之后放置的代码订阅IssuseReceived事件,并在$.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.
}
更新:

window.jsonIssues = {};  // or tack on to some other accessible var

$.getJSON("url", function(data) {
    window.jsonIssues = data.Issues;
});

// see results here
alert(window.jsonIssues);
或者,您可以全局存储数据,只需使用自定义事件通知已接收数据并更新全局变量

$(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:

window.jsonIssues = {};  // or tack on to some other accessible var

$.getJSON("url", function(data) {
    window.jsonIssues = data.Issues;
});

// see results here
alert(window.jsonIssues);
对此:

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

您应该避免使用同步AJAX调用阻塞浏览器的原因是阻塞的JavaScript线程会阻塞浏览器中的所有其他内容