Man*_*ngh 4 jquery cross-domain
我遇到了同步跨域调用问题.
在我的应用程序的早期,我们有域名调用,所以没有问题
我早期用于拨打电话的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);
}
Run Code Online (Sandbox Code Playgroud)
现在,当我们将调用移动到不同的域时,我们需要进行跨域调用,我在上面的代码中更改了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);
}
Run Code Online (Sandbox Code Playgroud)
当我在调用中输入"async:false"时,上面的Jquery更改工作正常,但据我所知,我们不能在跨域中进行同步调用,如果我更改为"async:true",则调用开始给出错误上线( for (i = 0, length = oData.length; i < length; i++))为OData的需要装上第二个"airportxml",似乎两个呼叫都依赖于对方,所以首先每当呼叫发送同时也适用于下一个电话也.
我也使用了ajaxQueue,但没有运气.
请建议我需要做哪些更改.
正如zi42和jQuery.ajax()文档所解释的那样,"跨域请求和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
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13376 次 |
| 最近记录: |