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));
它经历了以下步骤:
- 获取函数
is_it_complete
并将其命名为参数arg1
和arg2
。 - 获取函数
do_something
并使用上面的结果作为参数调用它。
当浏览器看到:
do_something(function () { is_it_complete(arg1, arg2) });
它确实:
- 创建一个调用
is_it_complete(arg1, arg2)
的函数对象is_it_complete(arg1, arg2)
- 获取函数
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”的调用永远不会被执行。