2010-03-24 4 views
0

Я пытаюсь реализовать интерфейс iGoogle как интерфейс панели управления, используя виджеты, которые получают свой контент с других сайтов, используя вызовы JSONP.порядок выполнения обратного вызова в jQuery getJSON

Проблема в том, что если первый виджет, который вызывает «$ .ajax», занимает 8 секунд, чтобы вернуть содержимое, кажется, что обратные вызовы других виджетов будут вызываться только после того, как обратный вызов первого виджета получит казнены. Для удобства пользователей было бы лучше, если бы виджеты могли отображаться, как только они вернут содержимое с удаленных сайтов, и не дожидаться тех, которые были запланированы до завершения.

Есть ли способ, которым я могу это сделать?

EDIT: Я использую jquery 1.4.1.

Я тестировал Chrome, и поведение, похоже, отличается от поведения в Firefox.

Вот скрипт, который я сделал, чтобы попытаться получить то, что происходит:

function showTime(add) { console.log(getTime() + ': ' + add); } 
    function getNow() { return new Date().getTime(); } 
    initialTime = getNow(); 
    function getTime() { return getNow() - initialTime; } 
    function display(data) { showTime('received a response'); } 

    showTime("Launched a request"); 
    jQuery.getJSON("http://localhost:51223/WaitXSeconds/3?callback=?", display); 
    showTime("Launched a request"); 
    jQuery.getJSON("http://localhost:51223/WaitXSeconds/4?callback=?", display); 
    showTime("Launched a request"); 
    jQuery.getJSON("http://localhost:63372/WaitXSeconds/9?callback=?", display); 
    showTime("Launched a request"); 
    jQuery.getJSON("http://services.digg.com/stories/top?appkey=http%3A%2F%2Fmashup.com&type=javascript&callback=?", display); 
    showTime("Launched a request"); 
    jQuery.getJSON("http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=?", display); 

Первые три вызова просто поддельные вызовы, ожидающие заданное количество секунд. Обратите внимание, что я использую два разных сервера, реализующих этот метод.

Вот результат в консоли на Firefox 3.6.2:

0: Launched a request 
3: Launched a request 
6: Launched a request 
11: Launched a request 
14: Launched a request 
3027: received a response 
7096: received a response 
9034: received a response 
9037: received a response 
9039: received a response 

.. и вот результат в Chrome 4.1.249.1036 (41514):

1: Launched a request 
2: Launched a request 
3: Launched a request 
4: Launched a request 
5: Launched a request 
165: received a response 
642: received a response 
3145: received a response 
7587: received a response 
9157: received a response 

Кажется, что в Firefox, два запроса к двум общедоступным API-адресам вызывают в конце, после того, как все остальные вызовы будут успешными.

Хром, с другой стороны, может выполнить обратный вызов, как только он получит ответ.

В обоих браузерах, когда запрос выполняется на том же сервере, они не выполняются параллельно. Они назначаются один за другим. Но я думаю, что это разумное поведение.

Может кто-нибудь объяснить поведение Firefox или есть какие-то взломы, чтобы обойти это?

+0

Это не звучит для меня. Порядок выполнения вызовов не должен влиять на порядок, в котором они возвращаются ... – Skilldrick

+0

Вы заставляете эти вызовы быть синхронными? –

+0

Какой браузер вы используете? Вы видите одно и то же поведение в разных браузерах? –

ответ

2

В Firefox, если один из одновременных запросов JSONP не завершен, то все последующие запросы JSONP не выполняются, даже если их ответы уже получены и записаны в эти теги. Это связано с тем, что < скрипт > теги, используемые JSONP, выполняются синхронно в Firefox. Так что если один < скрипт > не закончен, то последующие < сценарии > теги не выполняются, даже если они заполнены данными ответа.

Решение заключается в переносе параллельных запросов JSONP от iFrame. Существует проект под названием jquery-jsonp, который решает эту проблему.

Вот упрощенная версия фреймах JSONP:

var jsc = (new Date()).getTime(); 
function sendJsonpRequest(url, data, callback) { 
    var iframe = document.createElement("iframe"); 
    var $iframe = jQuery(iframe); 
    $iframe.css("display", "none"); 
    jQuery("head").append($iframe); 

    var iframeWindow = iframe.contentWindow; 
    var iframeDocument = iframeWindow.document; 

    iframeDocument.open(); 
    iframeDocument.write("<html><head></head><body></body></html>"); 
    iframeDocument.close(); 

    var jsonp = "jsonp" + jsc++; 
    var url = url + "?callback=" + jsonp; 
    var params = jQuery.param(data); 
    if (params) { 
     url += "&" + params; 
    } 

    // Handle JSONP-style loading 
    iframeWindow[jsonp] = function(data){ 
     if (callback) { 
      callback(data); 
     } 
     // Garbage collect 
     iframeWindow[jsonp] = undefined; 
     try{ delete iframeWindow[jsonp]; } catch(e){} 
     if (head) { 
      head.removeChild(script); 
     } 
     $iframe.remove(); 
    }; 

    var head = iframeDocument.getElementsByTagName("head")[0]; 
    var script = iframeDocument.createElement("script"); 
    script.src = url; 

    head.appendChild(script); 
} 
+0

Отличный ответ! Я уже перешел на jquery-jsonp, и теперь он работает как шарм. По-прежнему хорошо знать, что происходит. Спасибо. – lau

+0

Я хочу добавить здесь примечание. Я видел, что некоторые ребята писали, что jQuery.ajax() должен быть асинхронным. Ну, они правы, пока мы говорим об AJAX. Но jQuery.ajax ({dataType: "script"}) или jQuery.ajax ({dataType: "jsonp"}) или jQuery.getScript() или jQuery.getJSON с обратным вызовом =? параметр, эти методы не являются методами AJAX, но

2

Согласно jQuery.ajax() странице:

Первая буква в Ajax означает «асинхронный», что означает, что операция происходит параллельно и порядок выполнения не гарантируется.

Я не знаю, почему последние называемые виджеты возвращаются позже, но я не думаю, что это связано с вызовом JQuery, если, как и Питер предложил, пока вы явно установить async в false.

1

По умолчанию $.ajax is asynchronous.

asyncBoolean По умолчанию: истинно

Убедитесь, что вы не имеете его значение ЛОЖЬ.Отлаживайте запросы XHR с помощью Firebug, чтобы узнать, правильно ли отправлены запросы и почему dom не обновляется.

Вы можете ознакомиться с этим Tutorial, чтобы узнать, как использовать эти инструменты и как узнать, что не так с вашим графическим интерфейсом.

 Смежные вопросы

  • Нет связанных вопросов^_^