origin - jquery ajax header cross domain
jQuery cross-domain ajax: devoluciĆ³n de llamada cuando se ejecuta (2)
Esto es un poco desagradable pero ¿has intentado usar un iframe
? La idea es simple:
- Tenga un formulario con la
action
y elmethod
apropiados para la solicitud que está tratando de hacer. - Establezca el
target
( https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form ) del formulario para apuntar a uniframe
en su página, esteiframe
puede estar oculto. - Escuche la carga del
iframe
y cuando eliframe
haya cargado, puede ejecutar su código.
Así que aquí hay un pequeño ejemplo (usa jQuery):
<form id="xform" action="http://foo.bar/foo/bar" method="get" target="xiframe">
<input type="text" name="foo" value="bar" />
</form>
<iframe name="xiframe" id="xiframe"></iframe>
<script>
var form = $(''#xform''),
iframe = $(''#xiframe'');
iframe.load(function () {
// run your stuff here
});
form.submit();
</script>
Fondo
Estoy cargando y ejecutando un script desde otro servidor ( dominio cruzado ) a través de la llamada .ajax(...)
jQuery.
Hay un poco de código que debe ejecutarse después de que se haya ejecutado el código del otro servidor, porque de lo contrario algunos objetos aún no están definidos.
Quizás importante: el código remoto contiene otra getScript(...)
. Y tengo que esperar a que se ejecute este código también. No puedo simplemente cargar este segundo script desde mi código, porque su fuente es dinámica (es decir, depende de algunos resultados del script remoto).
No funcionó: devolución de llamada de success
Aparentemente, se llama a una devolución de llamada success
después de que se haya lanzado el código remoto, pero antes de que se ejecute el código remoto.
# coffee script
executeLater = ->
# this bit of code needs to run after the remote code has been executed.
console.log("yehaa!")
$.getScript("http://example.com/script-from-other-server.js")
.success(executeLater) # this gets executed when the remote script is loaded,
# but before the remote script is executed.
No funcionó: async: false
Aparentemente, el atributo async
se ignora para las solicitudes de dominios cruzados, como se indica aquí en la documentación de jQuery: http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings
Además, me gustaría evitar la configuración async: false
, porque se dice que bloquea el navegador.
# coffee script
executeLater = ->
# this bit of code needs to run after the remote code has been executed.
console.log("yehaa!")
$.ajax(
dataType: ''script'',
url: ''http://example.com/script-from-other-server.js'',
async: false # does not work because the request is cross domain
)
.success(executeLater)
No funcionó: $.when(...).then(...)
Usando el mecanismo de cuando-entonces de jQuery, aparentemente, el código then
se ejecuta antes de que se ejecute el bloque.
# coffee script
executeLater = ->
# this bit of code needs to run after the remote code has been executed.
console.log("yehaa!")
$.when( $.ajax(
dataType: ''script'',
url: ''http://example.com/script-from-other-server.js'',
) ).then(executeLater)
EDITAR: funcionó, pero inutilizable: ajax
ambos scripts
No puedo hacer esto en producción, como dije antes en la sección de "antecedentes", pero si reduzco todos los casos a uno y cargo el segundo, que generalmente es ejecutado por el script remoto, en mi propio script, todo funciona multa.
# coffee script
executeLater = ->
# this bit of code needs to run after the remote code has been executed.
console.log("yehaa!")
$.getScript("http://example.com/script-from-other-server.js")
.success( ->
$.ajax(
dataType: ''script'',
cache: true,
# I do not know this url in production:
url: ''http://example.com/another-script-from-the-remote-server.js''
)
.success(executeLater)
)
Cosas para evitar
Odiaría utilizar construcciones como un par de llamadas setTimout
hasta que se defina un determinado objeto y se ejecute el método executeLater()
.
Lo que necesito: una devolución de llamada executed
Sería perfecto utilizar un tipo de devolución de llamada executed
lugar de la devolución de llamada ajax
método ajax
. Pero, hasta ahora, no he encontrado esta devolución de llamada.
# coffee script
executeLater = ->
# this bit of code needs to run after the remote code has been executed.
console.log("yehaa!")
$.ajax(
dataType: ''script'',
url: ''http://example.com/script-from-other-server.js'',
executed: executeLater # <---- I NEED A CALLBACK LIKE THIS
)
¿Alguna pista?
¿Alguien sabe cómo puedo ejecutar el método executeLater
después de que se haya ejecutado el código remoto ? ¡Gracias!
EDITAR: política del mismo origen
Como Adeneo señaló en la sección de comentarios, la política de origen de JavaScript podría ser el problema.
El script, que cargo con una llamada ajax
o getScript
no puede cargar y ejecutar otro script desde un servidor remoto para evitar que un script malicioso "llame a casa".
Esto es respaldado por el siguiente experimento:
Esto no funciona:
<html><head>
<script language="javascript" src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script language="javascript">
jQuery.getScript("http://example.com/script-from-other-server.js")
</script>
</head><body></body></html>
Esto funciona:
De acuerdo con esta respuesta stackexchange , la política del mismo origen permite que scripts remotos cargados por una etiqueta html <script>
carguen otros scripts remotos a través de ajax
.
<html><head>
<script language="javascript" src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script language="javascript" src="http://example.com/script-from-other-server.js"></script>
</head><body></body></html>
La pregunta sigue siendo : ¿hay una buena manera de hacerlo con una llamada ajax, o tengo que "probar" que poseo este código insertando una etiqueta <script>
en el documento html?
Fondo
La sugerencia de adeneo de considerar JavaScripts Same-Origin Policy (ver comentarios a la pregunta) resolvió mi problema.
Cuando la pregunta asume que se llama al success
devolución de llamada antes de que el script solicitado se ejecute por completo, el problema real es que el script solicitado solicita otro script, como se indica en la pregunta:
Quizás importante: el código remoto contiene otra
getScript(...)
. Y tengo que esperar a que se ejecute este código también. No puedo simplemente cargar este segundo script desde mi código, porque su fuente es dinámica (es decir, depende de algunos resultados del script remoto).
Cuando el script solicitado se carga dinámicamente, esta segunda llamada a getScript
se evita mediante la política de origen de JavaScript.
Solución 1: Incluir la secuencia de comandos en el código html
Si uno tiene acceso a los archivos html, uno puede agregar una etiqueta de script con el script remoto como src
. Por lo tanto, uno "prueba" que uno realmente quiere cargar este script remoto y javascript ejecutará la llamada remota getScript
.
<html><head>
...
<script language="javascript" src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script language="javascript" src="http://example.com/script-from-other-server.js"></script>
</head><body></body></html>
Para ejecutar el código executeLater
, uno simplemente puede usar una devolución de llamada ready
:
# coffee script
executeLater = ->
# this bit of code needs to run after the remote code has been executed.
console.log("yehaa!")
$(document).ready(executeLater)
Solución 2: evitar la política de origen
Esto no es recomendable, pero es posible. Hay una pregunta popular de desbordamiento de pila sobre cómo evitar la política de origen idéntico:
Formas de eludir la política del mismo origen
Solución 3: realmente espere a que se ejecute el script
Si, además de la política del mismo origen, el script remoto realmente tarda tanto en ejecutarse que el script local tiene que esperar, se puede utilizar la solución iframe de Ahmed Nuaman:
https://.com/a/18793000/2066546