可能重复:
Can't access global variable in jQuery $.get within function
这可能是一个新手问题,但在这里:我宣布了一个名为preview的全局变量。使用AJAX,我得到一个json数组并循环遍历它。对于每次迭代,我都会进行另一次AJAX调用以获取字符串并将其附加到全局变量。
但是,在第二次AJAX调用之后打印全局变量会给我“空字符串”(我肯定会从第二次AJAX调用中返回一个字符串)。
以下是代码:
var preview;
$("#some-button").click(function(e){
e.preventDefault();
var companies = "blahblahblah";
$.ajax({
url: "tracklink/getemails.php",
type: "POST",
data: "companies=" + companies,
dataType: "json",
success: function(databack) {
if (databack) {
for (i=0; i<databack.length; i=i+1) {
preview = "";
$("#selected-clip-list li").each(function(){
$.ajax({
url: "tracklink/cksum.php",
type: "POST",
data: "video_id=" + $(this).attr("clip_id") + "&addr=" + databack[i].email_address,
success: function (msg) {
if (msg) {
preview += msg;
}
//this works
//console.log(preview);
}
});
});
//doesn't work
console.log(preview);
}
}
}
});
});
知道为什么我会得到“空字符串”吗?
非常感谢。
答案 0 :(得分:5)
因为Ajax是异步。这一行:
//doesn't work
console.log(preview);
在处理响应之前执行 。这就是为什么你提供一个回调函数(success:
)来处理响应的原因。
所有必须处理响应的代码必须在内部或从回调中调用。
与preview
无法在回调中访问(因为它可访问)无关。
更新:您可以使用Deferred
objects解决此问题:
success: function(databack) {
if (databack && databack.length > 0) {
var deferred = $.Deferred();
preview = "";
for (i=0; i<databack.length; i=i+1) {
$("#selected-clip-list li").each(function(){
deferred = deferred.pipe($.ajax({...}));
});
}
deferred.then(function() {
console.log(preview);
});
}
}
这将按顺序执行Ajax请求(但不阻塞),以便以正确的顺序将响应附加到preview
。但实际上我并不是100%清楚你要在preview
中收集哪些数据。你确定这个嵌套for循环是否正确?
如果您不关心Ajax请求的顺序,您也可以这样做:
var deferreds = [];
for (i=0; i<databack.length; i=i+1) {
$("#selected-clip-list li").each(function(){
deferreds.push($.ajax({...}));
});
}
$.when.apply($, deferreds).then(function() {
console.log(preview);
});
答案 1 :(得分:0)
不幸的是,因为AJAX请求是异步的,所以它不会像你期望的那样工作。您实际上是将预览设置为空,调度一堆请求,然后打印出空变量。请求将在稍后完成并填写,但它已经打印出来。
这是你所拥有的基本重写版本,但做得更好。请记住,在ajax请求完成之前,每个函数都会返回,然后在完成所有请求后调用下一个函数。这甚至可以避免使用丑陋的全局变量。
$("#some-button").click(function(e){
e.preventDefault();
$.ajax({
url: "tracklink/getemails.php",
type: "POST",
data: "companies=" + companies,
dataType: "json",
success: emailSuccess
});
// When the email list is returned,
// Look up previews for each one.
function emailSuccess(databack) {
if (databack) {
for (var i=0; i<databack.length; i=i+1) {
queryPreviews(databack[i]);
}
}
}
// Sends off ajax requests for the items
// and calls 'previewComplete' when the preview is ready.
function queryPreviews(data) {
var preview = "";
var completed = 0;
var items = $("#selected-clip-list li");
items.each(function(i){
$.ajax({
url: "tracklink/cksum.php",
type: "POST",
data: "video_id=" + $(this).attr("clip_id") + "&addr=" + data.email_address,
success: function (msg) {
completed++;
if (msg) {
preview += msg;
}
// When all of the ajax requests are done
// Call a function to do what needs to be done with preview
if (completed == items.length) {
previewComplete(preview);
}
}
});
});
}
// Do whatever you need to do with the preview
function previewComplete(preview) {
console.log(preview);
}
});