una termine que funcion esperar javascript ajax function

termine - Llamar a una función de JavaScript devuelta por una respuesta Ajax



esperar que termine una funcion javascript (17)

Tengo un sistema en el que envío un comando Ajax, que devuelve un bloque de script con una función. Después de que estos datos estén insertados correctamente en el DIV, quiero poder llamar a esta función para realizar las acciones requeridas.

es posible?


Nota : eval () puede ser mal utilizado fácilmente, digamos que la solicitud es interceptada por un tercero y le envía un código no confiable. Luego, con eval () estarías ejecutando este código no confiable. Consulte aquí los peligros de eval () .

Dentro del archivo HTML / Ajax / JavaScript devuelto, tendrá una etiqueta de JavaScript. Dale una identificación, como runScript . No es común agregar una identificación a estas etiquetas, pero es necesario hacer referencia a ella específicamente.

<script type="text/javascript" id="runscript"> alert("running from main"); </script>

En la ventana principal, llame a la función eval evaluando solo ese bloque NUEVO de código JavaScript (en este caso, se llama runscript ):

eval(document.getElementById("runscript").innerHTML);

Y funciona, al menos en Internet Explorer 9 y Google Chrome.


Código del lado PHP Nombre del archivo class.sendCode.php

<?php class sendCode{ function __construct($dateini,$datefin) { echo $this->printCode($dateini,$datefin); } function printCode($dateini,$datefin){ $code =" alert (''code Coming from AJAX {$this->dateini} and {$this->datefin}'');"; //Insert all the code you want to execute, //only javascript or Jquery code , dont incluce <script> tags return $code ; } } new sendCode($_POST[''dateini''],$_POST[''datefin'']);

Ahora desde su página Html debe activar la función ajax para enviar los datos.

.... <script src="http://code.jquery.com/jquery-1.9.1.js"></script> .... Date begin: <input type="text" id="startdate"><br> Date end : <input type="text" id="enddate"><br> <input type="button" value="validate''" onclick="triggerAjax()"/>

Ahora en nuestro script.js local definiremos el ajax

function triggerAjax() { $.ajax({ type: "POST", url: ''class.sendCode.php'', dataType: "HTML", data : { dateini : $(''#startdate'').val(), datefin : $(''#enddate'').val()}, success: function(data){ $.globalEval(data); // here is where the magic is made by executing the data that comes from // the php class. That is our javascript code to be executed } }); }



Creo que para interpretar correctamente su pregunta en esta forma: "OK, ya he terminado con todas las cosas de Ajax, solo deseo saber si la función de JavaScript que mi devolución de llamada Ajax insertada en el DIV se puede llamar en cualquier momento a partir de ese momento , es decir, no quiero llamarlo contextualmente al retorno de devolución de llamada ".

De acuerdo, si te refieres a algo como esto, la respuesta es sí, puedes invocar tu código nuevo en ese momento en cualquier momento durante la persistencia de la página dentro del navegador, bajo las siguientes condiciones:

1) Su código de JavaScript devuelto por la devolución de llamada de Ajax debe estar sintácticamente bien;
2) Incluso si su declaración de función se inserta en un bloque <script> dentro de un elemento <div> existente, el navegador no sabrá que la nueva función existe, ya que el código de declaración nunca se ha ejecutado. Por lo tanto, debe eval() su código de declaración devuelto por la devolución de llamada Ajax, para declarar efectivamente su nueva función y tenerla disponible durante toda la vida de la página.

Incluso si es bastante tonto, este código explica la idea:

<html> <body> <div id="div1"> </div> <div id="div2"> <input type="button" value="Go!" onclick="go()" /> </div> <script type="text/javascript"> var newsc = ''<script id="sc1" type="text/javascript">function go() { alert("GO!") }<//script>''; var e = document.getElementById(''div1''); e.innerHTML = newsc; eval(document.getElementById(''sc1'').innerHTML); </script> </body> </html>

No usé Ajax, pero el concepto es el mismo (incluso si el ejemplo que elegí seguro no es muy inteligente :-)

En términos generales, no cuestiono el diseño de su solución, es decir, si es más o menos apropiado externalizar + generalizar la función en un archivo .js separado y similares, pero tenga en cuenta que una solución de este tipo podría generar más problemas, especialmente si sus invocaciones de Ajax deben repetirse, es decir, si el contexto de la misma función debe cambiar o en caso de que se deba referir a la persistencia de la función declarada, entonces quizás deba considerar seriamente cambiar su diseño a uno de los ejemplos sugeridos en este hilo.

Finalmente, si malinterpreté su pregunta, y está hablando de la invocación contextual de la función cuando regresa su devolución de llamada Ajax, entonces mi opinión es sugerir el enfoque Prototype descrito por krosenvold , ya que es un navegador cruzado, probado y completamente funcional. y esto puede brindarle una mejor hoja de ruta para futuras implementaciones.


Es completamente posible, e incluso hay algunos casos de uso bastante legítimos para esto. Usando el marco de Prototype se hace de la siguiente manera.

new Ajax.Updater(''items'', ''/items.url'', { parameters: { evalJS: true} });

Ver la documentation del actualizador Ajax. Las opciones están en el conjunto de opciones comunes . Como de costumbre, hay algunas advertencias sobre a dónde apunta "esto", así que lea la letra pequeña.

El código de JavaScript se evaluará con la carga. Si el contenido contiene la función myFunc(), realmente podría decir myFunc() después. Tal vez de la siguiente manera.

if (window["myFunc"]) myFunc()

Esto verifica si la función existe. Tal vez alguien tenga una mejor forma de hacer esto en todos los navegadores que funcione en Internet Explorer 6.


Este código también funciona, en lugar de evaluar el html voy a agregar el script a la cabeza

function RunJS(objID) { //alert(http_request.responseText); var c=""; var ob = document.getElementById(objID).getElementsByTagName("script"); for (var i=0; i < ob.length - 1; i++) { if (ob[i + 1].text != null) c+=ob[i + 1].text; } var s = document.createElement("script"); s.type = "text/javascript"; s.text = c; document.getElementsByTagName("head")[0].appendChild(s); }


Esto no parece una buena idea.

Debe abstraer la función para incluir en el resto de su código JavaScript los datos devueltos por los métodos Ajax.

Por lo que vale, sin embargo, (y no entiendo por qué estás insertando un bloque de script en un div), incluso los métodos de script en línea escritos en un bloque de script serán accesibles.


He probado esto y funciona. ¿Cuál es el problema? Simplemente coloque la nueva función dentro de su elemento javascript y luego llámelo. Funcionará.


Lo resolví hoy al poner mi JavaScript en la parte inferior del HTML de respuesta.

Tenía una solicitud de AJAX que me devolvía un montón de HTML que se mostraba en una superposición. Necesitaba adjuntar un evento de clic a un botón en el HTML / superposición de la respuesta devuelta. En una página normal, envolvería mi JavaScript en "window.onload" o "$ (document) .ready" para que adjunte el controlador de eventos al objeto DOM después de que se haya procesado el DOM para la nueva superposición, pero porque esta fue una respuesta AJAX y no una nueva carga de página, ese evento nunca ocurrió, el navegador nunca ejecutó mi JavaScript, mi controlador de eventos nunca se adjuntó al elemento DOM, y mi nueva funcionalidad no funcionó. De nuevo, resolví mi "ejecución de JavaScript en un problema de respuesta AJAX" al no usar "$ (documento) .ready" en el encabezado del documento, sino colocando mi JavaScript al final del documento y haciendo que se ejecutara después del HTML / DOM ha sido renderizado.


Me gustaría agregar que hay una función eval en jQuery que le permite evaluar el código globalmente, lo que le permitirá deshacerse de cualquier problema contextual. La función se llama globalEval() y funcionó muy bien para mis propósitos. Su documentación se puede encontrar globalEval() .

Este es el código de ejemplo proporcionado por la documentación de la API jQuery:

function test() { jQuery.globalEval("var newVar = true;") } test(); // newVar === true

Esta función es extremadamente útil cuando se trata de cargar scripts externos dinámicamente que aparentemente intentabas hacer.


Mi función de llamada ajax habitual:

function xhr_new(targetId, url, busyMsg, finishCB) { var xhr; if(busyMsg !== undefined) document.getElementById(targetId).innerHTML = busyMsg; try { xhr = new ActiveXObject(''Msxml2.XMLHTTP''); } catch(e) { try { xhr = new ActiveXObject(''Microsoft.XMLHTTP''); } catch(e2) { try { xhr = new XMLHttpRequest(); } catch(e3) { xhr = false; } } } xhr.onreadystatechange = function() { if(xhr.readyState == 4) { if(xhr.status == 200) { var target = document.getElementById(targetId) target.innerHTML = xhr.responseText; var scriptElements = target.getElementsByTagName("script"); var i; for(i = 0; i < scriptElements.length; i++) eval(scriptElements[i].innerHTML); if(finishCB !== undefined) finishCB(); } else document.getElementById(targetId).innerHTML = ''Error code: '' + xhr.status; } }; xhr.open(''GET'', url, true); xhr.send(null); // return xhr; }

Alguna explicación:
targetId es un identificador de elemento (generalmente div) donde irá el texto del resultado de la llamada ajax.
url es la llamada ajax url.
busyMsg será el texto temporal en el elemento de destino.
finishCB a finishCB cuando la transacción ajax finalice correctamente.
Como puede ver en xhr.onreadystatechange = function() {...} todos los elementos <script> se recopilarán de la respuesta ajax y se ejecutarán uno por uno. Parece que funciona muy bien para mí. Los dos últimos parámetros son opcionales.


Parece un diseño bastante extraño para su código: por lo general, tiene más sentido hacer que sus funciones sean llamadas directamente desde un archivo .js, y luego solo recuperar datos con la llamada Ajax.

Sin embargo, creo que debería funcionar llamando a eval() en la respuesta, siempre que sea un código JavaScript sintácticamente correcto.


Probé todas las técnicas que se ofrecen aquí, pero finalmente la forma en que funcionó fue simplemente poner la función JavaScript dentro de la página / archivo donde se supone que debería pasar y llamarla desde la parte de respuesta del Ajax simplemente como una función:

... }, function(data) { afterOrder(); }

Esto funcionó en el primer intento, así que decidí compartirlo.


Si su script AJAX tarda más de un par de milisegundos en ejecutarse, eval () siempre se ejecutará y evaluará el elemento de respuesta vacío antes de que AJAX lo rellene con el script que está intentando ejecutar.

En lugar de perder el tiempo con timing y eval (), aquí hay una solución bastante simple que debería funcionar en la mayoría de las situaciones y que probablemente sea un poco más segura. El uso de eval () generalmente es desaprobado porque los caracteres que se evalúan como código pueden manipularse fácilmente desde el lado del cliente.

Concepto

  1. Incluya su función de JavaScript en la página principal. Escríbalo para que cualquier elemento dinámico pueda ser aceptado como argumento.
  2. En su archivo AJAX, llame a la función utilizando un evento DOM oficial (onclick, onfocus, onblur, onload, etc.). Dependiendo de los otros elementos en su respuesta, puede ser bastante listo para hacerlo sentir sin interrupciones. Pase sus elementos dinámicos como argumentos.
  3. Cuando su elemento de respuesta se llena y el evento tiene lugar, la función se ejecuta.

Ejemplo

En este ejemplo, deseo adjuntar una lista dinámica de autocompletado de la biblioteca jquery-ui a un elemento AJAX DESPUÉS de que el elemento se haya agregado a la página. Fácil, ¿verdad?

start.php

<!DOCTYPE html> <html> <head> <title>Demo</title> <!-- these libraries are for the autocomplete() function --> <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/ui-lightness/jquery-ui.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script> <script type="text/javascript"> <!-- // this is the ajax call function editDemoText(ElementID,initialValue) { try { ajaxRequest = new XMLHttpRequest(); } catch (e) { try { ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { return false; }}} ajaxRequest.onreadystatechange = function() { if ( ajaxRequest.readyState == 4 ) { var ajaxDisplay = document.getElementById(''responseDiv''); ajaxDisplay.innerHTML = ajaxRequest.responseText; } } var queryString = "?ElementID="+ElementID+"&initialValue="+initialValue; ajaxRequest.open("GET", "ajaxRequest.php"+queryString, true); ajaxRequest.send(null); } // this is the function we wanted to call in AJAX, // but we put it here instead with an argument (ElementID) function AttachAutocomplete(ElementID) { // this list is static, but can easily be pulled in from // a database using PHP. That would look something like this: /* * $list = ""; * $r = mysqli_query($mysqli_link, "SELECT element FROM table"); * while ( $row = mysqli_fetch_array($r) ) { * $list .= "/".str_replace(''"'',''/"'',$row[''element''])."/","; * } * $list = rtrim($list,","); */ var availableIDs = ["Demo1","Demo2","Demo3","Demo4"]; $("#"+ElementID).autocomplete({ source: availableIDs }); } //--> </script> </head> <body> <!-- this is where the AJAX response sneaks in after DOM is loaded --> <!-- we''re using an onclick event to trigger the initial AJAX call --> <div id="responseDiv"><a href="javascript:void(0);" onclick="editDemoText(''EditableText'',''I am editable!'');">I am editable!</a></div> </body> </html>

ajaxRequest.php

<?php // for this application, onfocus works well because we wouldn''t really // need the autocomplete populated until the user begins typing echo "<input type=/"text/" id=/"".$_GET[''ElementID'']."/" onfocus=/"AttachAutocomplete(''".$_GET[''ElementID'']."'');/" value=/"".$_GET[''initialValue'']."/" />/n"; ?>


Solo recuerda si creas una función de la manera siguiente a través de ajax ...

function foo() { console.log(''foo''); }

... y ejecutarlo a través de eval, es probable que tenga un problema de contexto. Toma esto como tu función de devolución de llamada:

function callback(result) { responseDiv = document.getElementById(''responseDiv''); responseDiv.innerHTML = result; scripts = responseDiv.getElementsByTagName(''script''); eval(scripts[0]); }

Estará declarando una función dentro de una función, por lo que esta nueva función solo estará disponible en ese alcance.

Si desea crear una función global en este escenario, puede declararlo de esta manera:

window.foo = function () { console.log(''foo''); };

Pero, también creo que no deberías estar haciendo esto ...

Perdón por cualquier error aquí ...


Una lista de verificación para hacer tal cosa:

  1. la respuesta Ajax devuelta es eval (ed).
  2. las funciones se declaran en forma func_name = function() {...}

Mejor aún, use frameworks que lo maneje como en Prototype . Tienes Ajax.updater .


La respuesta de Federico Zancan es correcta, pero no tiene que darle a su guión una identificación y evaluar todo su guión. Simplemente evalúa el nombre de tu función y se puede invocar.

Para lograr esto en nuestro proyecto, escribimos una función proxy para llamar a la función devuelta dentro de la respuesta Ajax.

function FunctionProxy(functionName){ var func = eval(functionName); func(); }