2012-05-28 3 views
4

Я застрял в синхронном вызове перекрестного вызова. неКак сделать синхронный вызов перекрестного вызова JSONP

Ранее в моем приложении у нас было домен вызова, поэтому не было никаких проблем

Мои Ранее Javascript код для создания вызова был ниже:

function EKXMLProvider(oDropdown, sDefault, sXML, sFilterUrl, fireRequestOnce) 
{ 
    var oXMLHTTP, i, length, oData, sValue, sDisplay, sName, sMatch, oRegExp; 

    if (!oDropdown) 
     return; 

    // XMLHTTP Object to retrieve the xml document 
    oXMLHTTP = this.createXMLHttpRequest(); 
    this.FilterUrl = sFilterUrl; 
    if (sFilterUrl != previousFilterUrl){ 
     oXMLHTTP.open("GET", sFilterUrl, false); 
     oXMLHTTP.send(null); 
     sFilterData = oXMLHTTP.responseText 
     previousFilterUrl = sFilterUrl; 
    } 
    if(!fireRequestOnce ||(fireRequestOnce && retrievedData == null)) 
    { 
     this.documentUrl = sXML; 
     oXMLHTTP.open("GET", this.documentUrl, false); 
     oXMLHTTP.send(null); 

     oData = oXMLHTTP.responseXML.documentElement.childNodes; 

     if(fireRequestOnce) 
      retrievedData = oData; 
    } 
    else if(retrievedData != null) 
    { 
     oData = retrievedData; 
    } 
    this.suggestData = new Array(); 

    // Filter out all 2 and 3 letter codes (airport, city, country) 
    oRegExp = new RegExp("\\s+\\(\\w{2,3}\\)", "gi"); 
    var iCount = 0  
    for (i = 0, length = oData.length; i < length; i++) 
    { 
     sValue = oData[i].attributes.getNamedItem("v").value; 
     sDisplay = oData[i].attributes.getNamedItem("d").value; 
     sName = oData[i].attributes.getNamedItem("n").value; 
     //sMatch = oData[i].attributes.getNamedItem("m").value; 
     sMatch = oData[i].attributes.getNamedItem("e").value; 

     if (sFilterData.search(sValue) != -1){ 
      this.suggestData[iCount] = new EKSuggestData(sName + " (" + sValue + ")", sDisplay, sValue, sMatch, sMatch.replace(oRegExp, "")); 
      iCount++; 
     } 
    } 

    // Call the inherited class 
    EKSuggestProvider.call(this, oDropdown, sDefault); 
} 

Теперь, как мы переехали наши звонки на другой домен , нам нужно сделать crossdomain звонков, я изменил выше код для crossdomain, как показано ниже:

function EKXMLProvider(oDropdown, sDefault, sXML, sFilterUrl, fireRequestOnce) 
{ 
    var oXMLHTTP, i, length, oData, sValue, sDisplay, sName, sMatch, oRegExp; 
    var qr = "&jsonpcall=true"; 
    if (!oDropdown) 
     return; 

    // XMLHTTP Object to retrieve the xml document 
    oXMLHTTP = this.createXMLHttpRequest(); 

    this.FilterUrl = sFilterUrl; 

    if (sFilterUrl != previousFilterUrl){ 
    //alert(sFilterUrl); 
     //oXMLHTTP.open("GET", sFilterUrl, false); 
     //oXMLHTTP.send(null); 
     //sFilterData = oXMLHTTP.responseText 

     // queue up an ajax request 
     $.ajax({ 
     url: sFilterUrl + qr, 
     type: "GET", 
     cache: true, 
     async:false, 
     contentType: "application/javascript; charset=utf-8", 
     dataType: "jsonp", 
     jsonpCallback: "airport", 
     success: function(data, textStatus, jqXHR) 
     {    
      if (data.airport[0] != '') 
      { 
        sFilterData = data.airport[0]; 
      } 
     } 
     }); 

     previousFilterUrl = sFilterUrl;   
    } 

    if(!fireRequestOnce ||(fireRequestOnce && retrievedData == null)) 
    { 
     //alert(sXML); 
     this.documentUrl = sXML; 
     //oXMLHTTP.open("GET", this.documentUrl, false); 
     //oXMLHTTP.send(null); 

     // queue up an ajax request 
      $.ajax({ 
      url: sXML + qr, 
      type: "GET", 
      async:false, 
      cache: true, 
      contentType: "application/javascript; charset=utf-8", 
      dataType: "jsonp", 
      jsonpCallback: "airportxml", 
      success: function(data, textStatus, jqXHR) 
      {     
        var xmlDoc = $.parseXML(data.myresult); 
       oData = xmlDoc.documentElement.childNodes; 
       alert(oData); 
      } 
      }); 

     //oData = oXMLHTTP.responseXML.documentElement.childNodes; 

     if(fireRequestOnce) 
      retrievedData = oData; 
    } 
    else if(retrievedData != null) 
    { 
     oData = retrievedData; 
    } 
    this.suggestData = new Array(); 

     // Filter out all 2 and 3 letter codes (airport, city, country) 
     oRegExp = new RegExp("\\s+\\(\\w{2,3}\\)", "gi"); 
     var iCount = 0  
    for (i = 0, length = oData.length; i < length; i++) 
    { 
     sValue = oData[i].attributes.getNamedItem("v").value; 
     sDisplay = oData[i].attributes.getNamedItem("d").value; 
     sName = oData[i].attributes.getNamedItem("n").value; 
     //sMatch = oData[i].attributes.getNamedItem("m").value; 
     sMatch = oData[i].attributes.getNamedItem("e").value; 

      if (sFilterData.search(sValue) != -1){ 
      this.suggestData[iCount] = new EKSuggestData(sName + " (" + sValue + ")", sDisplay, sValue, sMatch, sMatch.replace(oRegExp, "")); 
      iCount++; 
     } 
    } 

    // Call the inherited class 
    EKSuggestProvider.call(this, oDropdown, sDefault); 
} 

над изменений Jquery работает хорошо, когда я ставлю «асинхронной ложь, «в моем вызове, однако, по моим сведениям, мы не можем иметь синхронный вызов в кросс-домене, и если я перейду на« асинхронный: истинный », вызов начнет выдавать ошибку в строке (for (i = 0, length = oData.length; i < length; i++)), поскольку Одату необходимо заполнить на втором" airportxml ", и кажется, что оба вызова зависят друг от друга, поэтому всякий раз, когда первый вызов отправляется, он одновременно идет и для следующего вызова.

Для этого я использовал ajaxQueue, но не повезло.

Пожалуйста, представьте, какие изменения мне нужно сделать.

+0

Вы можете перенести этот код на обратный вызов ..ваш конструктор делает слишком много реальной работы, он должен просто построить и инициализировать объект – Esailija

+0

@Esailija можете ли вы, пожалуйста, очистить его больше, любую ссылку на образец или код –

ответ

4

Как поясняется zi42, а также по jQuery.ajax() documentation, «Междоменные запросы и dataType: "jsonp" запросов не поддерживают синхронную работу».

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

Обходной путь zi42, предложенный в комментарии - создание синхронного вызова Ajax в ваш собственный домен, а затем выполнение междоменного вызова с вашего сервера - лучший подход, который вы могли бы предпринять, если вы действительно хотите, чтобы он был синхронным.

Другой очевидный подход состоит в том, чтобы перестроить ваш код так, чтобы он работал асинхронно, помещая материал, который вы хотите сделать после каждого запроса jsonp, в обратный вызов успеха. То есть, в результате успешного обращения к первому запросу jsonp вы должны выполнить второй запрос jsonp. В течение успешного обратного вызова второй вы делаете какую-либо окончательную обработку. Если вам нужно передать окончательные результаты в другой части кода затем поместить код Ajax в функцию, которая принимает функцию обратного вызова в качестве параметра:

function doMyAjaxCalls(callbackFunc) { 
    // make first request 
    $.ajax({ 
     ... 
     dataType: "jsonp", 
     success: function(data, textStatus, jqXHR) { 
     // do something with first response, then 
     // make second request    
     $.ajax({ 
      ... 
      dataType: "jsonp", 
      success: function(data, textStatus, jqXHR) { 
       // do something with second response, then 
       // do final processing, then 
       callbackFunc(dataHere); 
      } 
     }); 
     } 
    }); 
} 

doMyAjaxCalls(function(response) { 
    // do something with response 
}); 
+0

Каким будет URL-адрес для обоих вызовов ajax? это будет тот же URL? Если да, то не будет ли он в то же время повторять одни и те же данные? – sarojanand

+0

@sarojanand - URL-адреса могут быть любыми. У ОП было два разных URL. – nnnnnn

3

Когда вы используете JSONP, запрос не выполняется через XHR, но добавив фактический тег <script> в DOM. Вот почему вы не можете сделать это синхронно. Это просто невозможно.

+0

Что такое другой вариант для реализации выше, используя jquery или что-либо? –

+2

Единственный вариант - иметь сценарий «прокси» в том же домене и передать ему URL-адрес, который вы хотите получить. Скажем, ваш javascript находится на 'domain1.com', и вы хотите выполнить запрос ajax на' http: // domain2.com/some_resource', тогда вы будете делать запрос ajax на http://domain1.com/domain2_proxy. php'. В domain2_proxy.php вы должны сделать запрос cURL на фактический URL-адрес, передав любой параметр, который был передан вам в '$ _GET'. Затем вы вернете форму ответа cURL. –

+0

Незначительная опечатка: jsonp не может быть _синхронным_. – nnnnnn

0

Другим вариантом было бы, чтобы блокировать пользовательский интерфейс (не блокирует выполнение).

Используйте что-то вроде BlockUI, которое будет «серо» на экране, пока ваш звонок не закончится.

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