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

Meg*_*att 45 javascript variables jquery scope callback

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

var jsonIssues = {};  // declare json variable

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

// jsonIssues not accessible here
Run Code Online (Sandbox Code Playgroud)

在另一篇文章中提到了类似这样的问题,并且一致认为我需要在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
Run Code Online (Sandbox Code Playgroud)

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

var jsonIssues = {};

$(document).ready(function() {

  var jsonIssues = {};  // declare json variable

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

  // now accessible?
}
Run Code Online (Sandbox Code Playgroud)

我的印象是,document.ready中声明的变量应该在document.ready的任何部分中"全局"可访问和修改,包括$ .getJSON回调函数等子函数.我可能需要阅读javascript变量范围,但似乎并不容易实现我想要的.感谢所有的回复.

更新#2: 根据以下答案的评论,我确实使用了$ .ajax 而不是 .getJSON,并取得了我想要的结果.代码如下:

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

    // jsonIssues accessible here -- good!!
Run Code Online (Sandbox Code Playgroud)

对我的答案进行后续评论(我非常欣赏他们).我这样做的目的是最初加载一个JSON对象,其中包含用户可以从中删除的问题列表,然后保存.但是,这是通过在页面上后续交互做,我不能预见用户将要使用JSON对象做回调.因此,一旦回调完成就需要使其可访问.有没有人在我的逻辑中看到一个缺陷?说真的,因为可能有些东西我没看到......

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

有没有人知道在这种情况下我应该如何阻止用户交互?为什么这么关注?再次感谢所有回复.

str*_*ger 35

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

所以,鉴于此:

a();

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

c();
Run Code Online (Sandbox Code Playgroud)

的调用的顺序a,b以及c可以是a b c(什么想要的,在这种情况下)或者a c b(更可能实际发生).

解决方案?

同步XHR请求

使请求同步而不是异步:

a();

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

c();
Run Code Online (Sandbox Code Playgroud)

重组代码

将呼叫移至呼叫cb:

a();

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

    c();
});
Run Code Online (Sandbox Code Playgroud)

  • 一个合理的答案.不幸的是(正如OP在问题更新中发现的那样),`$ .getJSON`不为`asynch`选项提供"选项覆盖".@Mega Matt:你必须调用`$ .ajax`*而不是*`$ .getJSON`,传递`dataType:"json"`以执行getJSON的相同工作. (4认同)

Dav*_*ard 9

请记住,当您提供回调函数时,其重点是将该回调的执行推迟到稍后并立即继续执行下一步.这是必要的,因为浏览器中的JavaScript的单线程执行模型.可以强制执行同步,但它会在整个操作期间挂起浏览器.在像$ .getJSON这样的情况下,浏览器停止响应的时间过长了.

换句话说,您正试图找到一种方法来使用这种程序范例:

var foo = {};

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

// Use foo here.
Run Code Online (Sandbox Code Playgroud)

当您需要重构代码以使其更像这样:

$.getJSON("url", function(data) {
  // Do something with data.property here.
});
Run Code Online (Sandbox Code Playgroud)

如果你想保持回调函数的简单,"做某事"可能是对另一个函数的调用.重要的是你要等到$ .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.
}
Run Code Online (Sandbox Code Playgroud)

更新:

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

$(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);
}
Run Code Online (Sandbox Code Playgroud)

更新2:

对此:

有没有人知道在这种情况下我应该如何阻止用户交互?为什么这么关注?再次感谢所有回复.

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


小智 5

也许这项工作,对我有用.. :)

$variable= new array();

$.getJSON("url", function(data){
asignVariable(data);
}

function asignVariable(data){
$variable = data;
}

console.log($variable);
Run Code Online (Sandbox Code Playgroud)

希望它能帮到你.. :)