2012-05-28 4 views
4

동기식 크로스 도메인 호출로 막혔습니다. 앞서 우리가 도메인 호출을 가지고 있었던 내 응용 프로그램에서 동기식 JSONP 크로스 도메인 호출을 만드는 방법

, 그래서 거기 아무 문제 없습니다

내 전화를 만들기위한 자바 스크립트 코드 아래이었다 이전 :

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

이제 우리는 다른 도메인에 대한 우리의 통화를 이동로 우리는 내가 다음과 같이 교차 도메인에 대한 코드 위에 변경, 도메인 간 통화를 할 필요가 : 나는 "비동기 넣을 때 jQuery를 변경 위

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

이 잘 작동됩니다 거짓, "내 전화로, 그러나 내 지식에 따라 우리는 동기식 호출을 가질 수 없다. 크로스 도메인에서 호출 할 수 없다. 그리고"async : true "로 변경하면 (for (i = 0, length = oData.length; i < length; i++)) 라인에서 오류가 발생한다. Odata는 두 번째" airportxml "로 표시되며 두 통화가 서로 종속되어 있으므로 첫 번째 통화가 전송 될 때마다 다음 통화도 동시에 진행됩니다.

이 경우에도 ajaxQueue를 사용했지만 행운은 없습니다.

변경해야 할 사항을 제안하십시오.

+0

해당 코드를 콜백으로 옮길 수 있습니다.생성자가 너무 많은 실제 작업을 수행하면 개체를 생성하고 초기화해야합니다. – Esailija

+0

@Esailija 더 ​​많은 샘플 링크 또는 코드를 제발 할 수 있습니까? –

답변

4

zi42 및 jQuery.ajax() documentation에서 설명한 것처럼 '도메인 간 요청 및 dataType: "jsonp" 요청은 동기식 연산을 지원하지 않습니다.'

동기식 호출은 응답이 돌아올 때까지 브라우저를 잠그기 때문에 동기식 호출이 좋지 않은 사용자 경험을하는 경향이 있기 때문에 표준적인 경우에도 동기식 호출을 수행하는 것이 분명합니다. 구현하기 쉬운 Ajax. 2 개의 동기 호출을 연속적으로 만들어서 더 나빠질 수 있기를 원합니다.

주석에 제안 된 해결 방법 - 사용자의 도메인에 동기식 Ajax 호출을 작성한 다음 서버에서 도메인 간 호출을 수행하는 방식이 실제로 동기를 취할 때 취할 수있는 최선의 방법입니다.

또 다른 명백한 접근법은 코드를 재구성하여 각 jsonp 요청 이후 원하는 작업을 성공 콜백에 넣음으로써 비동기 적으로 작동하도록하는 것입니다. 즉, 첫 번째 jsonp 요청의 성공 콜백 내에서 두 번째 jsonp 요청을 수행 할 것입니다. 두 번째 호출의 성공 콜백 내에서 최종 처리를 수행합니다.

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은 어떻게 될까요? 그것은 동일한 URL이 될 것인가? 그렇다면이 경우 동일한 데이터를 두 번 호출하지 않겠습니까? – sarojanand

+0

@sarojanand - URL은 무엇이든 될 수 있습니다. OP에는 두 개의 다른 URL이 있습니다. – nnnnnn

3

JSONP를 사용할 때 요청은 XHR을 통해 수행되지 않고 실제로 <script> 태그를 DOM에 추가합니다. 그래서 동기를 만들 수 없습니다. 단순히 불가능합니다.

+0

jquery 또는 기타를 사용하여 위의 것을 구현하는 다른 옵션은 무엇입니까 –

+2

유일한 옵션은 동일한 도메인에 "프록시"스크립트를 가져 와서 검색하려는 URL을 전달하십시오. 귀하의 자바 스크립트가'domain1.com'에 있고'http : // domain2.com/some_resource'에 대한 ajax 요청을하고 싶다면, 당신은'http://domain1.com/domain2_proxy '로 ajax 요청을 할 것입니다. php'. domain2_proxy.php에서'$ _GET'에 전달 된 매개 변수를 전달하여 실제 URL에 대한 cURL 요청을합니다. 그런 다음 응답 양식 cURL을 반환합니다. –

+0

사소한 오자 정정 : jsonp는 _ 동기 _ 일 수 없습니다. – nnnnnn

0

는 또 다른 옵션 (실행을 차단하지 UI를 차단하는 것입니다 : 당신은 당신의 코드의 다른 부분에 최종 결과를 전달해야하는 경우 다음 매개 변수로 콜백을받는 함수의 Ajax 코드를 넣어).

BlockUI과 같은 것을 사용하면 통화가 끝날 때까지 화면이 회색으로 표시됩니다.

관련 문제