Jquery延迟回拨奇怪

我正在玩jQuery中的回调函数和延迟函数,并且想知道是否有人能告诉我为什么这有效

http://jsfiddle.net/austinbv/QVujr/

get_each_total = function(callback) { var requests; requests = []; var url; url = "http://otter.topsy.com/search.js?callback=?&apikey=38A260E9D12A4908B1AF9184B691131&q=justin+bieber&window=d"; return requests.push($.getJSON(url, function(data) { })); return $.when.apply($, requests).then(function() { callback(); }, function() { return alert("There was an error communicating with a remote library, try again in a few"); }); }; get_each_total_broken = function(callback) { var requests; requests = []; var url; url = "http://otter.topsy.com/hjhkl/sehjkhhkjhkarch.js?callback=?&apikey=38A260E9D12A4908B1AF9184B691131&q=justin+bieber&window=d"; return requests.push($.getJSON(url, function(data) { })); return $.when.apply($, requests).then(function() { callback(); }, function() { return alert("There was an error communicating with a remote library, try again in a few"); }); }; $(function () { get_each_total(alert("success")); get_each_total_broken(alert("fail")); }); 

而这不是

http://jsfiddle.net/austinbv/wzve6/

  get_each_total = function(callback) { var requests; requests = []; var url; url = "http://otter.topsy.com/search.js?callback=?&apikey=38A260E9D12A4908B1AF9184B691131&q=justin+bieber&window=d"; return requests.push($.getJSON(url, function(data) { })); return $.when.apply($, requests).then(function() { callback(); }, function() { return alert("There was an error communicating with a remote library, try again in a few"); }); }; get_each_total_broken = function(callback) { var requests; requests = []; var url; url = "http://otter.topsy.com/hjhkl/sehjkhhkjhkarch.js?callback=?&apikey=38A260E9D12A4908B1AF9184B691131&q=justin+bieber&window=d"; return requests.push($.getJSON(url, function(data) { })); return $.when.apply($, requests).then(function() { callback(); }, function() { return alert("There was an error communicating with a remote library, try again in a few"); }); }; $(function () { get_each_total(function () { alert("success")}); get_each_total_broken(function () {alert("fail")}); }); 

正如您所看到的,唯一的区别在于最后两行,其中匿名函数包装了回调。 任何见解都会很好。

这段代码:

 return requests.push($.getJSON(url, function(data) { })); 

退出你的function。 永远不会调用callback

PS当你说the only difference is an anonymous function wrapping the callback ,你暗示你也在代码的第一个版本中传递了一个函数。 那不是真的; 你试图传递任何alert('whatever'); 正在回归,这是undefined

进一步说明:

你的两个函数( get_each_total ,& get_each_total_broken )都希望参数是一个函数。 您可以在稍后的代码( callback() )中将其称为函数,这一点很明显。 但是,这一行:

 get_each_total(alert("success")); 

没有将函数传递给get_each_total 。 它相当于以下内容:

 var returnedFromAlert = alert("success"); get_each_total(returnedFromAlert); 

所以,基本上,你没有将任何东西传递给你的get_each_total函数。 在调用get_each_total之前,您会立即获得success警报

 get_each_total(function () { alert("success")}); 

在这里你有function (){ alert ....返回一个函数对象

  get_each_total(alert("success")); 

这里alert("success")是一个alert()返回类型的对象,它不是一个函数。

编辑: –响应评论我将进一步澄清。

当浏览器看到

 do_something(is_it_complete(arg1, arg2)); 

它经历了以下步骤:

  1. 获取函数is_it_complete并将其命名为参数arg1arg2
  2. 获取函数do_something并使用上面的结果作为参数调用它。

当浏览器看到:

 do_something(function () { is_it_complete(arg1, arg2) }); 

它确实:

  1. 创建一个调用is_it_complete(arg1, arg2)的函数对象is_it_complete(arg1, arg2)
  2. 获取函数do_something并将上述对象作为参数调用它。

编辑3: –好的,在第一个调用警报之前,它在运行代码之前就已经开始工作了。

你有:

 get_each_total = function(callback) { // ... *snip* return requests.push($.getJSON(url, function(data) {})); return $.when.apply($, requests).then(function() { // ... *snip* }); }; 

永远不会达到第二次回归。

编辑: –我想在阅读代码后会提出一些提示:

 var requests; requests = []; 

风格是多余的变化

 var requests = []; var url = " ...."; 

当你没有将任何参数传递给回调时,不要包装它。

 .then(function(){ callback();}) 

它是一样的:

 .then(callback); 

并且如评论中提到的你的url

 url = "http://otter.topsy.com/hjhkl/sehjkhhkjhkarch.js?callback=?&apikey=38A260E9D12A4908B1AF9184B691131&q=justin+bieber&window=d"; 

应该

 url = "http://otter.topsy.com/hjhkl/sehjkhhkjhkarch.js?callback=somevalue&apikey=38A260E9D12A4908B1AF9184B691131&q=justin+bieber&window=d"; 

甚至:

 url = "http://otter.topsy.com/hjhkl/sehjkhhkjhkarch.js" $.getJSON(url, { "callback": "somevalue", "apikey": "38A260E9D12A4908B1AF9184B691131", "q": "justin bieber", "window": "d" }, function(data){ alert("Got: " + data);}); 

这两个例子都不奏效。 (提示评论者:这是他说的最后两行。)

在第一个示例中, 即使在get_each_total()函数之前也会调用alert()来引发警报对话框 Javascript调用它,显示警报(并给出错觉而不是发生的事情),并将alert()调用的结果传递给get_each_total() (并且也对以下函数中的警报执行相同操作)。 结果为null。 如果调用了回调,则会引发错误。

在第二个示例中,您将声明一个函数并将对它的引用传递给get_each_total() ,然后可以通过您的callback()表达式callback() 。 函数是响应()运算符的东西,意思是“执行此操作”。 如果您的代码成功,它实际上会做一些事情(显示警报)。

但是你的代码没有。 走到小提琴,看着控制台,我看到这样的消息:“无法加载资源:服务器响应状态为500(内部服务器错误)。” getJSON()永远不会触发回调,因为它永远不会成功

[编辑] @austinbv向我指出我错过了什么。 500代码是他的故意测试。 但他的代码仍然在get_each_total_broken()被破坏; 在线上有一个错位的return

 return requests.push($.getJSON(url, function(data) { })); 

这将立即从get_each_total_broken返回。 永远不会调用when().then()子句,因此他永远不会看到error handling。 第一个例子中警报的即时性继续给出了发生某些事情的错觉。

您的代码有2个问题:

1)在最后两行代码中:第一个示例是将“alert”方法的执行结果传递给“get_each_total”和“get_each_total_broken”方法。 第二个例子是传递一个函数,该函数在执行时将调用“alert”。 第二个例子是正确的执行方法。

例如:

 function test(v) { // do something return null; } // executes "test" immediately and passes it's result to "someOtherFunction" someOtherFunction(test(v)); // will pass a function to "someOtherFunction" to be executed later someOtherFunction(function(){ test("value"); }); 

2)您的两种方法都有2个“返回”语句。 方法中遇到的第一个“返回”将返回它的值并退出方法; 从而导致第二个“返回”语句永远不会被执行。 因此,两种方法中对“$ .when.apply”的调用永远不会被执行。