我试图使用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' ...!?
}
这个问题是不是封闭的,问题是异步函数。 $获得()连接到服务器,并在服务器返回一个答案运行其回调函数。 但是,$。获得()完成,一旦请求被发送 ,而不是当返回响应。 因此,在执行回调函数前的最后两年的console.log()线运行。
你只能访问headers
和countryData
变量一旦回调函数执行,并且您知道已经发生的唯一地方是回调函数本身内。 或其他代码,它调用。
它不是一个封闭的问题。 这只是该行代码不会在它们的排列顺序执行。
这是一个基本事件的编程问题:过程的结束是在代码的中间。 一旦你知道它这是不是一个大问题。 你只需要编写过程结束在正确的地方。
在你的情况,事情发生的顺序如下:
步骤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", ..'
$.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
});