我有:
function loadGraphs(datawijk){
$.ajax({
url: './api5.php', //the script to call to get data
data: {
wijk: datawijk,
}, //you can insert url argumnets here to pass to api.php
//for example "id=5&parent=6"
dataType: 'json', //data format
success: function(rows) //on recieve of reply
{
var htmlContent = "";
// ADD TO
htmlContent += '<tr><th scope="row">Geboortes</th>';
$.each(rows, function(i, data) {
$.each(data, function(j, year) {
htmlContent +=
'<td>' + year + '</td>';
});
});
htmlContent += '</tr>';
var lol = updateOverlijdens(datawijk, htmlContent);
alert(lol);
$('#graphs table tbody').html(htmlContent);
}
});
}
function updateOverlijdens(datawijk, htmlContent){
$.ajax({
url: './api4.php', //the script to call to get data
data: {
wijk: datawijk,
}, //you can insert url argumnets here to pass to api.php
//for example "id=5&parent=6"
dataType: 'json', //data format
success: function(rows) //on recieve of reply
{
// ADD TO
htmlContent += '<tr><th scope="row">Overlijdens</th>';
$.each(rows, function(i, data) {
$.each(data, function(j, year) {
htmlContent +=
'<td>' + year + '</td>';
});
});
htmlContent += '</tr>';
return htmlContent;
}
});
}
当我做alert(lol);在函数loadGraphs我得到未定义…当我使用alert(htmlContent);在函数updateOverlijdens中,就在我返回值之前,我得到了正确的值。只有当我警告函数loadGraphs中的值时,才会得到未定义。我该如何解决这个问题?
你得到未定义的原因是你没有从updateOverlijdens
返回任何东西(但从内部函数成功)
你正在运行异步代码,通常你不能使用你正在使用的当前函数返回模式轻松解决这个问题,因为数据在返回的时候是不可用的。你需要的是回调。
请参阅此页的良好使用示例jQuery ajax。您需要做的是将一个函数传递给updateOverlijdens,并在ajax的成功回调触发时调用它。网上(以及上面的链接)有很多这样的例子。
下面的例子是你的代码被修改为正确的回调模式,解决了异步执行的问题
function loadGraphs(datawijk){
$.ajax({
url: './api5.php', //the script to call to get data
data: {
wijk: datawijk,
}, //you can insert url argumnets here to pass to api.php
//for example "id=5&parent=6"
dataType: 'json', //data format
success: function(rows) //on recieve of reply
{
var htmlContent = "";
// ADD TO
htmlContent += '<tr><th scope="row">Geboortes</th>';
$.each(rows, function(i, data) {
$.each(data, function(j, year) {
htmlContent +=
'<td>' + year + '</td>';
});
});
htmlContent += '</tr>';
updateOverlijdens(datawijk, htmlContent,function(lol){
alert(lol);
$('#graphs table tbody').html(lol);
});
}
});
}
function updateOverlijdens(datawijk, htmlContent,callback){
$.ajax({
url: './api4.php', //the script to call to get data
data: {
wijk: datawijk,
}, //you can insert url argumnets here to pass to api.php
//for example "id=5&parent=6"
dataType: 'json', //data format
success: function(rows) //on recieve of reply
{
// ADD TO
htmlContent += '<tr><th scope="row">Overlijdens</th>';
$.each(rows, function(i, data) {
$.each(data, function(j, year) {
htmlContent +=
'<td>' + year + '</td>';
});
});
htmlContent += '</tr>';
callback(htmlContent)
}
});
}
正如许多答案所解释的那样,问题在于您试图将AJAX调用中的某些内容返回给发起调用的函数。这是行不通的,因为调用者不会等待AJAX调用完成,并且会在AJAX调用完成之前返回。这就是关于异步调用的全部思想:你不想为了等待结果而阻塞执行。
处理这个问题的一种方法是传递一个回调函数,该函数需要在检索结果时执行。然后,这个函数将从AJAX成功回调中调用。另一个有趣的方法是使用jQuery的deferred和promises。一个承诺代表一个值,这个值将在将来的某个地方被取回。递延函数产生一个承诺,并在以后解决它。例如,所有的AJAX函数都返回一个承诺,你可以从任何jQuery对象中检索一个承诺,当所有动画完成时,这个承诺就会被解析。
在您的示例中,您可以创建一个延迟,它在检索AJAX结果时由htmlContent
解析。你从函数中返回延迟的承诺,这样调用者就可以将回调函数绑定到它,或者将它与其他承诺组合在一起。
function updateOverlijdens(datawijk) {
// Create the deferred
var dfd = new jQuery.Deferred();
// Initiate the AJAX request
$.ajax({
url: './api4.php',
data: {
wijk: datawijk,
},
dataType: 'json',
success: function(rows) {
var htmlContent = '<tr><th scope="row">Overlijdens</th>';
$.each(rows, function(i, data) {
$.each(data, function(j, year) {
htmlContent += '<td>' + year + '</td>';
});
});
htmlContent += '</tr>';
// Resolve the deferred
dfd.resolve(htmlContent);
},
error: function() {
// An error occurred, reject the deferred
dfd.reject();
}
});
// Return a promise
return dfd.promise();
}
开始编辑
感谢Benjamin Gruenbaum指出了我对延迟反模式的使用。以下是使用.then
进行链接的实现:
function updateOverlijdens(datawijk) {
return $.ajax({
url: './api4.php',
data: {
wijk: datawijk,
},
dataType: 'json'
}).then(function(rows) {
var htmlContent = '<tr><th scope="row">Overlijdens</th>';
$.each(rows, function(i, data) {
$.each(data, function(j, year) {
htmlContent += '<td>' + year + '</td>';
});
});
htmlContent += '</tr>';
return htmlContent;
});
}
结束编辑
你可以在你的loadGraphs
AJAX成功回调中使用承诺,像这样:
// Produce the table header
var htmlContent = '<tr><th scope="row">Geboortes</th>';
$.each(rows, function(i, data) {
$.each(data, function(j, year) {
htmlContent += '<td>' + year + '</td>';
});
});
var promise = updateOverlijdens(datawijk);
promise.then(function(htmlOverlijdens) {
// Append to the previously created HTML content
htmlContent += htmlOverlijdens;
// Apply the HTML
$('#graphs table tbody').html(htmlContent);
});
使用承诺的优点是它们给调用者提供了更多的灵活性。调用者可以很容易地使用then()
注册多个回调,使用jQuery.when()
将其与其他承诺组合,或者使用
pipe()
then
将结果管道到另一个承诺。
是。没有错。您需要在$.ajax之外定义函数的返回值。在你的代码中,你返回值到$。而不是updateOverlijdens。正确的代码需要是:
function updateOverlijdens(datawijk, htmlContent){
$.ajax({ ....})
return 'some value'
}