【问题标题】:JavaScript variable empty after call of getJSON() [duplicate]调用 getJSON() 后 JavaScript 变量为空 [重复]
【发布时间】:2017-06-13 01:06:59
【问题描述】:

我在从 JSON 文件导入数据时遇到了这个问题。我使用.getJSON 函数来获取数据,这意味着根据控制台日志工作,但是一旦我移出 getJSON 子函数,data2 中的数组就会消失。我在这里把它缩小到这个部分:

function prepData() {
    data2 = [];

    $.getJSON('http://localhost/data').done(function(json) {
        data2 =json;
        console.log(data2);
    });

    console.log(data2);
    SelectedData = data2;
    return SelectedData;
};

这可能是什么问题?

【问题讨论】:

  • 异步代码(如您对 getJSON 的调用)不会导致您的代码在完成之前暂停执行。这就是为什么它是异步的。

标签: javascript getjson


【解决方案1】:

你的功能:

function(json) {
    data2 = json;
}

之后执行

console.log(data2);
SelectedData = data2;

data2 那时还没有定义。


(1) function prepData(){
(2)    data2 = []; 

(3)    $.getJSON('http://localhost/data').done(function(json) {
(4)        data2 =json;
(5)        console.log(data2);
       });

(6)    console.log(data2);
(7)    SelectedData= data2;
(8)    return SelectedData;
   };

执行顺序:

1 -> 2 -> 3 -> 6 -> 7 -> 8 -> 4 -> 5

常见做法 - 返回承诺而不是数据:

function prepData(){
    return $.getJSON('http://localhost/data');
}

// more code here

prepData().done(function(json){
    console.log(json);
});

看看这些更详细的演示。
ES5 上的 jQuery:https://jsfiddle.net/DerekL/xtmy6po0/

function timeout(n){
    // create promise
    var defer = $.Deferred();

    // resolve after n milliseconds
    setTimeout(function(){
        defer.resolve(n);
    }, n);

    // return new promise that apply custom text
    return defer.then(function(v){
        return "Resolved after " + (v/1000) + " seconds";
    });
}

timeout(3000).then(function(message){
    // will be executed after 3 seconds
    alert(message);
});

等效的 ES7:https://jsfiddle.net/DerekL/8kLknbne/

async function timeout(n){
    // create timer
    let timer = () => new Promise(resolve => setTimeout(() => resolve(n), n));
    // return message
    return "Resolved after " + (await timer()/1000) + " seconds";
}

// call
timeout(3000).then(alert);

【讨论】:

  • 那是愚蠢的。有什么方法可以改变让 Json 按照写下的顺序运行?
  • @Exostrike 这就是 Promise 的设计方式。请记住,您只有一个线程,并且您不能阻止线程,因为它也会阻止所有 UI 更新。与其返回数据,不如返回 promise(或 jQuery 中的延迟对象)。
  • @Exostrike 如果您在处理异步调用方面需要更多帮助,请查看此演示:jsfiddle.net/DerekL/xtmy6po0
  • @Exostrike 这是最新 ES7 中的一段等效代码,而不是使用 jQuery:jsfiddle.net/DerekL/8kLknbne
【解决方案2】:

.done 是一个事件,因此它会比其他脚本晚几毫秒或几秒后发生,它仅在对 http://localhost/data 的请求完成时发生

这将首先运行:

$.getJSON('http://localhost/data');
console.log(data2);
SelectedData= data2;
return SelectedData;

几秒钟后 .done 事件将被触发 那么这将运行

data2 =json;
console.log(data2);

我的建议是在 .done 函数中调用另一个处理答案的函数,而不是等待返回值,该返回值将在您的代码中以未定义的形式返回

【讨论】:

    【解决方案3】:

    $.getJSON 是异步的,因此它将与您的下一个控制台语句并行执行。

    【讨论】:

    • 不。 JavaScript 是单线程的,这意味着(4)和(5)(参考我的回答)必须在函数返回后执行。
    • 不会并行执行。它将在当前代码执行完成后的某个时间点执行。 (在没有其他要执行的代码时到达执行堆栈的顶部)。
    • @t.niese 感谢您的澄清。这就是我想说的。
    猜你喜欢
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 1970-01-01
    • 2014-11-08
    • 2021-03-18
    • 1970-01-01
    相关资源
    最近更新 更多