2011-03-18 14 views
17

En mi aplicación, estoy usando Ext.Ajax.request para cargar scripts que ejecuto con eval.¿Cómo puedo hacer que la ejecución del código JavaScript espere hasta que se cargue y ejecute una solicitud AJAX con script?

El problema es que ya que lleva tiempo completar la solicitud AJAX, código que se ejecuta posteriormente y que necesita variables que están en el script cargado en AJAX. En este ejemplo, muestro cómo es este el caso. ¿Cómo puedo cambiar este código para que la ejecución del JavaScript después de AJAX espere hasta que se haya cargado y ejecutado el script en la llamada AJAX?

testEvalIssue_script.htm:

<script type="text/javascript"> 
    console.log('2. inside the ajax-loaded script'); 
</script> 

main.htm:

<html> 
    <head> 
     <script type="text/javascript" src="ext/adapter/ext/ext-base.js"></script> 
     <script type="text/javascript" src="ext/ext-all-debug.js"></script> 
     <script type="text/javascript"> 
      function loadViewViaAjax(url) { 
       Ext.Ajax.request({ 
        url: url, 
        success: function(objServerResponse) { 
         var responseText = objServerResponse.responseText; 
         var scripts, scriptsFinder=/<script[^>]*>([\s\S]+)<\/script>/gi; 
         while(scripts=scriptsFinder.exec(responseText)) { 
          eval.call(window,scripts[1]); 
         } 
        } 
       }); 
      } 

      console.log('1. before loading ajax script'); 
      loadViewViaAjax('testEvalIssue_script.htm'); 
      console.log('3. after loading ajax script'); 
     </script> 
    </head> 
    <body> 

    </body> 

</html> 

salida:

1. before loading ajax script 
3. after loading ajax script 
2. inside the ajax-loaded script 

¿Cómo puedo conseguir que la salida sea en el orden correcto, como esto:

1. before loading ajax script 
2. inside the ajax-loaded script 
3. after loading ajax script 
+4

Poner 2. donde 3. es y poner 3. donde 2. es? –

+0

¿Llamar a una función una vez completada la solicitud AJAX y mostrar un mensaje de "Cargando ..." al usuario? – Kevin

Respuesta

12

Ajax es asíncrona, lo que significa que la llamada se envía ajax, pero su código sigue funcionando tan feliz como antes sin parar. Ajax no detiene/pausa la ejecución hasta que se recibe una respuesta. Tendrás que agregar una función de devolución de llamada adicional o algo así.

<html> 
    <head> 
     <script type="text/javascript" src="ext/adapter/ext/ext-base.js"></script> 
     <script type="text/javascript" src="ext/ext-all-debug.js"></script> 
     <script type="text/javascript"> 
      function loadViewViaAjax(url, callback) { 
       Ext.Ajax.request({ 
        url: url, 
        success: function(objServerResponse) { 
         var responseText = objServerResponse.responseText; 
         var scripts, scriptsFinder=/<script[^>]*>([\s\S]+)<\/script>/gi; 
         while(scripts=scriptsFinder.exec(responseText)) { 
          eval.call(window,scripts[1]); 
         } 
         callback.call(); 
        } 
       }); 
      } 

      console.log('1. before loading ajax script'); 
      var afterAjax = function(){ 
       console.log('3. after loading ajax script'); 
      } 
      loadViewViaAjax('testEvalIssue_script.htm', afterAjax); 
     </script> 
    </head> 
    <body> 

    </body> 

</html> 
3

Desde la llamada AJAX es asíncrono, si se desea ejecutar algo que depende de los datos cargados a través de AJAX, que tendrá que ejecutarlo en el método de éxito. Coloque el código en otro método y luego llame a ese método después de las declaraciones de evaluación.

<script type="text/javascript"> 
      function doSomeAmazingThings() { 
       // amazing things go here 
      } 

      function loadViewViaAjax(url) { 
       Ext.Ajax.request({ 
        url: url, 
        success: function(objServerResponse) { 
         var responseText = objServerResponse.responseText; 
         var scripts, scriptsFinder=/<script[^>]*>([\s\S]+)<\/script>/gi; 
         while(scripts=scriptsFinder.exec(responseText)) { 
          eval.call(window,scripts[1]); 
         } 
         doSomeAmazingThings(); 
         console.log('3. after loading ajax script'); 
        } 
       }); 
      } 

      console.log('1. before loading ajax script'); 
      loadViewViaAjax('testEvalIssue_script.htm'); 
     </script> 
+1

Sí, pero, para que quede claro, debería mostrar la tercera declaración de la consola movida a la devolución de llamada o a su nueva función falsa. Como se muestra, sigue siendo bastante confuso para alguien que no comprende el problema. –

1

Usted podría intentar hacer la llamada AJAX sincrónica ... Por supuesto que tendría que dejar de usar la biblioteca Ext.Ajax, pero vale la pena si necesita resultados ajax antes de la siguiente línea de código.

Así es como mis páginas de intranet se comunican con mi base de datos. Hay un revés que descubrí, en el sentido de que no se pueden ver actualizaciones de páginas hasta que Javascript ceda el control a la página, por lo que cosas como una barra de estado, una barra de progreso o una superposición son imposibles con Ajax síncrono (No es cierto para mi firefox , se actualiza incluso dentro del código síncrono en algunas circunstancias).

Uso esto - es un poco casero y desordenado, pero ha funcionado impecablemente durante años en mi círculo. Simplemente cree un nuevo AJAX(), configure el url, agregue consultas (pares de nombre/valor) según sea necesario, configure asíncrono a falso, y cuando llame a Execute desde una función, se bloqueará hasta que regrese el Ajax.

O, si desea utilizarlo de forma asincrónica, simplemente escriba una nueva función "preestablecida" para el objeto AJAX que cree y cambie asíncrona a verdadera.

Escribí esto hace muchos años, por lo que no es el más adecuado, y hay maneras de hacer las cosas de manera diferente, pero funciona como un manual, y puede modificarlo como desee sin tener que depender de otra biblioteca.

function AJAX(){ 

//Declarations 
    var thisExt=this; //To be referenced by events 

//Initialize Properties 
    thisExt.URL=""; 
    thisExt.Query=""; 
    thisExt.Method="GET"; 
    thisExt.Asynchronous=true; 
    thisExt.Encoding="application/x-www-form-urlencoded"; 
    thisExt.PostData=""; 

// Provide the XMLHttpRequest class for IE 5.x-6.x: 
// Other browsers (including IE 7.x-8.x) ignore this 
// when XMLHttpRequest is predefined 
if (typeof XMLHttpRequest == "undefined") { 
    try { 
     thisExt.XMLHTTP = new ActiveXObject("Msxml2.XMLHTTP.6.0"); 
    } 
    catch (e1) { 
     try { thisExt.XMLHTTP = new ActiveXObject("Msxml2.XMLHTTP.3.0"); } 
     catch (e2) { 
      try { thisExt.XMLHTTP = new ActiveXObject("Msxml2.XMLHTTP"); } 
      catch (e3) { 
       try { thisExt.XMLHTTP = new ActiveXObject("Microsoft.XMLHTTP"); } 
       catch (e4) { 
        throw new Error("This browser does not support XMLHttpRequest."); 
       } 
      } 
     } 
    } 
} else { 
    thisExt.XMLHTTP = new XMLHttpRequest(); 
} 


//Methods 
    thisExt.XMLHTTP.onreadystatechange = function(){ 
     if(thisExt.XMLHTTP.readyState==4){ 
      window.status=""; 
      thisExt.onready(thisExt);//Passes thisExt so that the callback will have assess to the entire object, not just the returned text. 
     }else{ 
      window.status=thisExt.XMLHTTP.readyState;//Just for debugging 
     } 
    } 
    thisExt.addQuery=function(name,value){ 
     if(thisExt.Query!=""){ 
      thisExt.Query+="&" 
     } 
     thisExt.Query+=encodeURIComponent(name)+"="+encodeURIComponent(value) 
    } 

//Not really necessary, you could just say AjaxObj.URL="bla bla" 
    thisExt.setURL=function(URL){ 
     thisExt.URL=URL; 
    } 
//Not really necessary, you could just say AjaxObj.Query="bla bla" 
    thisExt.setQuery=function(Query){ 
     thisExt.Query=Query; 
    } 
//Not really necessary, you could just say AjaxObj.Method="bla bla" 
    thisExt.setMethod=function(Method){ 
     thisExt.Method=Method; 
    } 
//Not really necessary, you could just say AjaxObj.Encoding="bla bla" 
    thisExt.setEncoding=function(Encoding){ 
     thisExt.Encoding=Encoding; 
    } 
//Not really necessary, you could just say AjaxObj.PostData="bla bla" 
    thisExt.setPostData=function(PostData){ 
     thisExt.PostData=PostData; 
    } 

    thisExt.Execute=function(){ 
     if(thisExt.URL==""){ 
      alert("AJAX.URL cannot be null.") 
      return; 
     } 
     var URL2=thisExt.URL; 
     if(thisExt.Query!=""){ 
      URL2=URL2+"?"+thisExt.Query; 

     } 
     if(thisExt.Method=="POST"){ 
      //this.XMLHTTP.setRequestHeader("Content-Type",this.Encoding); 
      thisExt.XMLHTTP.open("POST", URL2, thisExt.Asynchronous); 
      thisExt.XMLHTTP.send(thisExt.PostData); 
     } else { 
      thisExt.XMLHTTP.open("GET", URL2, thisExt.Asynchronous); 
      thisExt.XMLHTTP.send(null); 
     } 
    } 

//Events & callbacks 
    thisExt.onready=function(){} 
} 
1

Esto puede lograrse mediante la creación de un objeto XMLHttpRequest y llamando a la función open con el parámetro asíncrono ajustado a falso.

var xmlhttp = new XMLHttpRequest(); 
xmlhttp.open("GET", "ajax_info.txt", false); 
var response = xmlhttp.responseText; 
Cuestiones relacionadas