Comment faire synchrone JSONP crossdomain appel
Je me suis coincé avec synchrone crossdomain appel.
Plus tôt dans mon application, nous étions en train de domaine, alors il n'y a pas de problèmes
Mon précédent code javascript pour faire appel, en tant que ci-dessous:
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);
}
Maintenant que nous avons déménagé nos appels d'autre domaine, nous avons besoin de faire crossdomain appels, j'ai changé le code ci-dessus pour crossdomain comme ci-dessous:
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);
}
Au-dessus de Jquery modifications fonctionnent très bien quand j'ai mis "async:false," à mon appel, mais, par ma connaissance nous n'avons pas d'appel synchrone dans le domaine de la croix et si je change pour "async:true," l'appel commence à donner de l'erreur sur la ligne ( for (i = 0, length = oData.length; i < length; i++))
Odata des besoins à pourvoir sur la deuxième "airportxml" et il semble à la fois les appels sont dépendantes les unes des autres, de sorte que chaque fois que premier appel est de l'envoyer simultanément va pour le prochain appel.
J'ai utilisé ajaxQueue pour cela aussi, mais pas de chance.
Veuillez indiquer quels sont les changements que je dois faire.
pouvez-vous s'il vous plaît vider plus, tout échantillon lien ou le code
OriginalL'auteur Manoj Singh | 2012-05-28
Vous devez vous connecter pour publier un commentaire.
Comme l'a expliqué zi42, et par la
jQuery.ajax()
de la documentation, 'des requêtes inter-domaine etdataType: "jsonp"
demandes ne prennent pas en charge le fonctionnement synchrone.'Ce n'est pas une mauvaise chose, étant donné qu'un appel synchrone a tendance à entraîner une mauvaise expérience utilisateur car il bloque le navigateur jusqu'à ce que la réponse est de retour, alors j'aimerais orienter clairement de faire un appel synchrone, même avec le standard de l'Ajax où il est facile à mettre en œuvre. Vous voulez faire deux appels synchrones en ligne donc, ce serait encore pire.
La solution de contournement zi42 suggéré dans un commentaire - faire un appel Ajax synchrone à votre propre nom de domaine et ensuite la réalisation de la croix-domaine d'appel à partir de votre serveur est la meilleure approche que vous pouvez prendre si vous voulez vraiment être synchrone.
L'autre approche évidente est de restructurer votre code pour qu'il fonctionne de manière asynchrone, en mettant les choses que vous voulez faire après chaque requête jsonp dans la réussite de rappel. C'est dans la réussite de rappel de la première requête jsonp vous souhaitez faire de la de faire de la deuxième requête jsonp. Au sein de la réussite de rappel de la deuxième tu ferais tout traitement final. Si vous avez besoin de transmettre les résultats finaux à l'autre partie de votre code, puis mettre le code Ajax dans une fonction qui prend une fonction de rappel qu'un paramètre:
Les Url peuvent être n'importe quoi. L'OP a deux Url différentes.
OriginalL'auteur nnnnnn
Lorsque vous utilisez JSONP, la demande n'est pas effectué par XHR, mais en ajoutant une réelle
<script>
balise pour les DOM. C'est pourquoi vous ne pouvez pas vous rendre synchrone. Il n'est tout simplement pas possible.La seule option est d'avoir un "proxy" script sur le même domaine, et en passant l'URL que vous souhaitez récupérer. Dire que votre javascript est sur
domain1.com
et vous voulez faire une requête ajaxhttp://domain2.com/some_resource
, alors vous feriez la requête ajaxhttp://domain1.com/domain2_proxy.php
. Dans domain2_proxy.php, vous souhaitez faire une demande cURL sur l'URL, en passant un paramètre qui a été transmis dans$_GET
. Ensuite vous retourner le formulaire de réponse cURL.Mineur correction faute de frappe: jsonp ne peut pas être synchrone.
Merci j'ai fait la correction 🙂
zi42, je n'ai pas de proxy type d'appel, la mise en œuvre, comme si je suis de nouveau aller à l'appel domaine1 qu'est-ce que l'utilisation de crossdomain appel direct, je veux quelque chose comme ci-dessus implmentation...s'il vous plaît suggérer que c'est vraiment une douleur pour moi
OriginalL'auteur ziad-saab
Une autre option serait de bloquer l'INTERFACE utilisateur (ne pas bloquer l'exécution).
Utiliser quelque chose comme BlockUI qui "gris" à l'écran jusqu'à ce que votre appel se termine.
OriginalL'auteur Serge Shultz