(仍然)更混淆JavaScript的关闭,Ajax和返回值((still) more confusi

2019-10-31 20:26发布

我试图使用jQuery获得()方法和一个javascript for循环从外部文件处理一些数据。 我读过有关封锁和从回调计算器上的返回值了几个小时,我仍然感到困惑,为什么这是行不通的。

是变量countryData不是全球范围相对于内回调函数? 他们被分配值如预期的回调函数中,但后来我如何访问它们一旦完成? 并可能wihtout使用警报()函数的例子吗?

function processData(inCSV){
    var headers;  
    var countryData = [];
    $.get(inCSV, function(data) {
        var lines = data.split('\r\n');
        for(var i=0;i<=lines.length-1;i++){
            var lineData = lines[i].split(',');
            if(i != 0){
                countryData[lineData[1]] = lineData.slice(2,lineData.length);
            } else {
                headers = lineData.slice(2,lineData.length);
            }
        }
        console.log('inside',headers);  // output 'inside ["1971", "1972", "1973" ...'
        console.log('inside',countryData['Brazil']);  // output 'inside ["56.4", "54.6", ..'
    });
    console.log('outside',headers);  // output 'outside undefined' ...!?
    console.log('inside',countryData['Brazil']);    // output 'outside undefined' ...!?
}   

Answer 1:

这个问题是不是封闭的,问题是异步函数。 $获得()连接到服务器,并在服务器返回一个答案运行其回调函数。 但是,$。获得()完成,一旦请求被发送 ,而不是当返回响应。 因此,在执行回调函数前的最后两年的console.log()线运行。

你只能访问headerscountryData变量一旦回调函数执行,并且您知道已经发生的唯一地方是回调函数本身内。 或其他代码,它调用。



Answer 2:

它不是一个封闭的问题。 这只是该行代码不会在它们的排列顺序执行。

这是一个基本事件的编程问题:过程的结束是在代码的中间。 一旦你知道它这是不是一个大问题。 你只需要编写过程结束在正确的地方。

在你的情况,事情发生的顺序如下:

步骤1.国家变量的声明与此代码:

var headers;  
var countryData = [];

第2步:您调用服务器使用此代码

$.get(inCSV, <CALLBACK>)

在这一点上有什么在回调已经完全没有意义。 它不会被执行,直到服务器响应回来。

第3步:您可以使用状态变量,此代码

console.log('outside',headers);  // output 'outside undefined' ...!?
console.log('inside',countryData['Brazil']);    // output 'outside undefined' ...!?

他们是不确定的,这是完全可预期的,因为没有代码初始化它们。

第4步:响应返回从服务器:

    var lines = data.split('\r\n');
    for(var i=0;i<=lines.length-1;i++){
        var lineData = lines[i].split(',');
        if(i != 0){
            countryData[lineData[1]] = lineData.slice(2,lineData.length);
        } else {
            headers = lineData.slice(2,lineData.length);
        }
    }
    console.log('inside',headers);  // output 'inside ["1971", "1972", "1973" ...'
    console.log('inside',countryData['Brazil']);  // output 'inside ["56.4", "54.6", ..'


Answer 3:

$.get异步的 ,这意味着脚本的其余部分将不会等待它完成。 您可以使用jQuery.Deferred类( 文档 ),以减轻这一点,如果你需要比由成功回调提供了更多的控制,也可以拨打电话同步 (意为脚本的其余部分等待其执行前完成) 。

同步AJAX调用

你需要使用$.ajax ( 文档 ),只是通过式async:false

$.ajax({
  url: inCSV,
  async: false,
  success: function() { /* ... */ }
});

// code here will not execute until the ajax call above is complete

递延对象

function processData(inCSV) {
    var deferred = jQuery.Deferred();
    $.ajax({
        url: inCSV, 
        success: function(data){
            // do stuff
            deferred.resolve([data]);
        },
        error: function() {
            deferred.reject();
        }
    });
    return deferred;
}

processingData = processData(inCSV);

// any code that doesn't care about the processing results can go here

// code that relies on headers or countryData must go in a block like this
// you can add as many "done" blocks as you like
processingData.done(function(data){
    // mess with data here
});


文章来源: (still) more confusion over javascript closures, ajax, and return values