Jquery отложил перезвонить странность - PullRequest
0 голосов
/ 02 сентября 2011

Я играл с обратными вызовами и отложенными функциями в 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")});
});

Как вы можете видеть, единственная разница заключается в последних двух строках, где анонимная функция переносит обратный вызов.Любое понимание было бы хорошо.

Ответы [ 4 ]

3 голосов
/ 02 сентября 2011

Этот кусок кода:

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

выходит из вашей функции.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 функцию.Вы получаете success оповещение сразу, до того, как get_each_total был вызван.

2 голосов
/ 02 сентября 2011
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 и назовите ее аргументами arg1 и arg2.
  2. получите функцию do_something и вызовите ее с результатом вышеописанногов качестве аргумента.

Когда браузер видит:

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

, он делает:

  1. Создает объект функции, который вызывает is_it_complete(arg1, arg2)
  2. Получите функцию do_something и вызовите ее с указанным выше объектом в качестве аргумента.

Edit 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);});
1 голос
/ 02 сентября 2011

Ни один из примеров не работает. (Намек рецензентам: это последние две строки, о которых он говорит.)

В первом примере вы вызываете alert(), который вызывает диалоговое окно с предупреждением, даже до вызова функции get_each_total(). Javascript вызывает его, показывая предупреждение (и давая иллюзию чем-то произошло) и передает результат вызова alert() на get_each_total() (и делает то же самое с предупреждением в следующей функции). Результат нулевой. Если бы когда-либо вызывался обратный вызов, это вызвало бы ошибку.

Во втором примере вы объявляете функцию и передаете ссылку на нее в get_each_total(), которая затем может быть вызвана через ваше выражение callback(). Функция - это что-то, что отвечает на оператор (), что означает «сделать это». Он действительно что-то сделает (покажет предупреждение), если ваш код завершится успешно.

Но ваш код - нет. Идя к скрипке и глядя на консоль, я вижу это сообщение: «Не удалось загрузить ресурс: сервер ответил со статусом 500 (Внутренняя ошибка сервера)». getJSON() никогда не запускает обратный вызов, потому что он никогда не завершается .

[EDIT] @austinbv указал мне, что я что-то пропустил. Код 500 - это преднамеренный тест с его стороны. Но его код все еще не работает в get_each_total_broken(); есть неуместный return в строке

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

Возвращается сразу с get_each_total_broken. Предложение when().then() никогда не вызывается, поэтому он никогда не видит обработки ошибок. Непосредственность предупреждений в первом примере продолжает создавать иллюзию того, что что-то произошло.

0 голосов
/ 02 сентября 2011

Есть 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 никогда не будет выполнен.Соответственно, вызов «$ .when.apply» в обоих методах никогда не будет выполнен.

...