2013-01-20 190 views
1

这是我有:JavaScript函数被未定义

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; 
     } 
    }); 
} 

当我做警报(笑);在函数loadGraphs我得到undefined ... 当我做alert(htmlContent);在函数updateOverlijdens就在我返回值之前,我知道它是正确的。只有当我警告我的函数loadGraphs中的值,我得到了未定义。我怎样才能解决这个问题?

+0

您忘记了发布“updateOverlijdens”的代码。 – Pointy

+1

@点击滚动。 :P –

+0

阿贾克斯仍** ** asynchronos ** – Bergi

回答

1

正如很多答案的解释,问题是,你想回来从AJAX调用返回的东西,其发起呼叫的功能。这是行不通的,因为调用者不会等待AJAX​​调用完成,并在完成之前返回。这就是关于异步调用的所有想法:您不希望阻止执行以等待结果进入。

处理此问题的一种方法是传递一个回调函数,该函数需要在结果被检索。这个函数将在AJAX成功回调中被调用。

另一个有趣的方法是利用jQuery的deferred s和promise s。承诺代表将在未来某处获得的某种价值。延迟产生承诺并在稍后解决。例如,所有AJAX函数都会返回一个promise,并且您可以从任何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(); 
} 

BEGIN编辑

感谢本杰明Gruenbaum指出我的deferred anti-pattern的使用。下面是使用.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

+1

嗨,我现在明白承诺比我以前好很多。请考虑用适当的'.then'调用替换[延迟反模式](https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns#the-deferred-anti-pattern)。谢谢。即返回$ .ajax(...)。然后(函数(行){...返回...}) –

+0

@BenjaminGruenbaum谢谢指出!答案已更新。 –

4

你越来越不确定的原因是,不必返回从updateOverlijdens任何东西(但在成功的内部函数)

您正在运行的异步代码,通常你不能使用当前轻松解决这个问题函数返回模式,因为数据在返回时不可用。你需要的是回调。

请参阅this page以了解jQuery ajax的使用示例。你会想要做的是传递一个函数updateOverlijdens,并在你的ajax的成功回调触发时调用它。网上有很多例子(以及上面的链接)。

这里有个例子是被修改到解决它与asyncrhonous执行问题的正确回调格局之后,你的代码

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) 
     } 
    }); 
} 
+0

在这种情况下,您可以轻松创建并传递回调以执行'$('#graphs table tbody')。html(htmlContent );'。然后,不是在'updateOverlijdends'中返回'htmlContent',而是使用'htmlContent'作为参数来调用传递的回调。 –

+0

下来选民,请问你不想找到满意的? –

0

是。没有错误。您需要为您的函数定义返回值,而不是使用$ .ajax。在你的代码中,你将值返回给$ .ajax,而不是updateOverlijdens。正确的代码必须是:

function updateOverlijdens(datawijk, htmlContent){  
    $.ajax({ ....}) 
    return 'some value' 
} 
+1

* real *问题是OP想要返回在AJAX调用中检索到的值。 –

+0

是的,我需要在ajax调用的值 – nielsv

+0

然后在ajax回调后做你的警报 - 警报(html内容) –