【问题标题】:Jquery deferred call back oddnessJquery延迟回调奇怪
【发布时间】:2011-09-02 01:51:28
【问题描述】:

我正在玩 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")});
});

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

【问题讨论】:

  • 我认为您将相同的代码粘贴了两次。
  • @matt nope 看看每个代码的最后 4 行
  • 对于以后的问题,请将相同的方法只发布一次。这将使我们不必扫描和比较它们,然后才能告诉您是什么导致了您的问题。谢谢。

标签: jquery callback jquery-deferred


【解决方案1】:

这段代码:

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

退出你的函数。 callback 永远不会被调用。

附:当您说the only difference is an anonymous function wrapping the callback 时,您暗示您还在代码的第一个版本中传递了一个函数。那不是真的;您正在尝试传递 alert('whatever'); 返回的任何内容,即 undefined

进一步说明:

您的两个函数(get_each_totalget_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 警报

【讨论】:

  • 你能详细说明你的最后一段吗
  • 我明白你在说什么cl.ly/0h2L0J2t0X0s2U090201 jsfiddle.net/austinbv/wzve6/2
  • @austinbv:你为什么在返回 JSONP 的服务上使用 $.getJSON
  • 是的,我知道我是为这个例子做的,添加一个回调=?使用 $.getJSON,让 jQuery 做一些魔术并运行包装函数,那么为什么不使用 $.getJSON
【解决方案2】:
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)的函数对象
  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);

如 cmets 中所述,您的网址

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

【讨论】:

  • 那么为什么不能将回调包装在匿名函数中,代码的构建方式不应该在延迟完成后运行回调?
  • 必须将代码包装在一个函数中。 function(){ ... } 是函数类型的对象。 alert() 表示获取此函数的结果。我将添加更多内容来解释情况。
  • 那么为什么在包装时警报永远不会被调用
  • 啊...如果你点击 jsfiddle 中的“整理”按钮,你会看到问题:你有return requests.push( ...,下一行是return $.when.apply( ...
  • @austinbv 你有.js?callback=?& 用一些东西替换第二个?(例如.js?callback=n&
【解决方案3】:

这两个例子都不起作用。 (给审稿人的提示:这是他所说的最后两行。)

在您的第一个示例中,您调用 alert(),这会引发警报对话框,甚至在调用 get_each_total() 函数之前。 Javascript 调用它,显示警报(并给出比发生了一些事情),并将alert() 调用的结果传递给get_each_total()(并且在以下函数中也对警报执行相同的操作)。结果为空。如果曾经调用过回调,则会引发错误。

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

但您的代码没有。转到小提琴并查看控制台,我看到以下消息:“加载资源失败:服务器响应状态为 500(内部服务器错误)。” getJSON() 永远不会触发回调,因为 它永远不会成功

[编辑] @austinbv 向我指出我错过了一些东西。 500 代码是他故意的测试。但是他的代码仍然在get_each_total_broken() 中被破解;该行中有一个错位的return

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

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

【讨论】:

  • 这就是延迟失败的关键,如果您查看 getJSON 的工作方式,它们会作为承诺传递给 $.when(),然后 $.then() 处理它们。两者都被调用,500 错误调用失败的回调。而对 topsy 的 api 调用的成功调用会触发成功回调。在你的控制台中设置一些断点,你会看到:)
  • 我的意思是,第一个中的 alerts() 不是回调,不能工作。我刚刚注意到,在您的第二个示例中,requests.push 行中有一个return 调用,它返回requests.push 的结果,并且永远不会到达您的when().then() 子句,所以这为什么不起作用。
  • 看看我在 stackoverflow.com/questions/7278511/… 上的 cmets 你会看到即使删除了返回,也不会调用失败回调
  • +1 这是正确答案,而且您似乎比我早 9 分钟找到了它。不错!
【解决方案4】:

您的代码有 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 个“return”语句。在方法中遇到的第一个“return”将返回它的值并退出该方法;从而导致第二个“return”语句永远不会被执行。因此,在这两种方法中对“$.when.apply”的调用永远不会被执行。

【讨论】:

  • 如果您查看jsfiddle.net/austinbv/wzve6/2,我已经删除了退货,但 $.then 的失败仍然不会运行
  • 我回答的第 1 部分仍然回答了您的问题。我用一个代码示例对其进行了修改以使其更加清晰。
  • 那么为什么它在我的第一条评论中没有运行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-09
  • 2017-06-02
  • 2014-07-31
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多