Javascript函数未定义


Javascript function gets undefined

我有:

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' 
}