如何使同步JSONP跨域调用 [英] How to make synchronous JSONP crossdomain call

查看:174
本文介绍了如何使同步JSONP跨域调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了同步跨域调用。

I got stuck with synchronous crossdomain call.

在我的应用程序的早期,我们有域名调用,所以没有问题

Earlier in my application we were having domain call, so there were no issues

我的早期javascript代码进行调用如下:

My Earlier javascript code for making call was as below:

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代码如下:

Now as we moved our calls to different domain, we need to make crossdomain calls, I changed above code for crossdomain as below:

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更改工作正常,当我把async:我的调用,但是根据我的知识,我们不能在跨域中进行同步调用,如果我更改为async:true,调用开始给线错误(for(i = 0, length = oData.length; i 因为Odata需要在第二个airportxml上填充,看起来两个调用都是相互依赖的,所以每当第一次调用

Above Jquery changes are working fine when I put "async:false," in my call, however as per my knowledge we can't have synchronous call in cross domain and if I change to "async:true," the call starts giving error on the line ( for (i = 0, length = oData.length; i < length; i++)) as Odata needs to be filled on the second "airportxml" and it seems both the calls are dependent on each other, so whenever first call is send it simultaneously goes for next call also.

我也使用了ajaxQueue,但没有运气。

I used ajaxQueue for this also, but no luck.

请建议我需要做哪些更改。

Please suggest what changes do I need to do.

推荐答案

如zi42解释和 jQuery.ajax()文档,'跨域请求和 dataType:jsonp请求不支持同步操作。

As explained by zi42, and by the jQuery.ajax() documentation, 'Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation.'

这不是一件坏事,同步调用往往会导致糟糕的用户体验,因为它锁定了浏览器,直到响应回来,所以我会避免做同步调用,即使使用标准的Ajax,它很容易实现。

This is not a bad thing, given that a synchronous call tends to result in a poor user experience because it locks up the browser until the response comes back, so I'd steer clear of making a synchronous call even with standard Ajax where it is easy to implement. You want to make two synchronous calls in a row so that would be even worse.

在一个注释中建议使用zi42的解决方法 - 对自己的域进行同步Ajax调用,然后从您的服务器进行跨域调用 - 如果您真的希望它是同步的,则是最好的方法。

The workaround zi42 suggested in a comment - making a synchronous Ajax call to your own domain and then making the cross-domain call from your server - is the best approach you could take if you really want it to be synchronous.

另一个明显的方法是重组代码,以便它将异步工作,通过将你想要做的每个jsonp请求后的东西成功回调。也就是说,在第一个jsonp请求的成功回调中,你将继续进行第二个jsonp请求。在第二个的成功回调中,你会做任何最后的处理。如果你需要将最终结果传递给代码的另一部分,然后将Ajax代码放在一个函数中,该函数将回调作为参数:

The other obvious approach is to restructure your code so that it will work asynchronously, by putting the stuff you want to do after each jsonp request into the success callback. That is, within the success callback of the first jsonp request you'd go on to make the second jsonp request. Within the success callback of the second you'd do any final processing. If you need to pass the final results to another part of your code then put the Ajax code in a function that takes a callback as a parameter:

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

这篇关于如何使同步JSONP跨域调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆