2011-10-16 9 views
7

la siguiente prueba es básicamente ~ 1000 operaciones matemáticas y funciona bien en la mayoría de los navegadores de PC y Android, y iOS 4.x. En iOS5 safari (iPhone 4 y iPad 2) obtenemos "JavaScript: Error undefined La ejecución de JavaScript excedió el tiempo de espera". Cualquier ayuda muy apreciada gracias.Javascript IOS5 "ejecución de JavaScript excedió el tiempo de espera"

/** Converts numeric degrees to radians */ 
if (typeof (Number.prototype.toRad) === "undefined") { 
    Number.prototype.toRad = function() { 
    return this * Math.PI/180; 
    } 
} 

function gc(lat1, lon1, lat2, lon2) { 
    // returns the distance in km between a pair of latitude and longitudes 
    var R = 6371; // km 
    var dLat = (lat2 - lat1).toRad(); 
    var dLon = (lon2 - lon1).toRad(); 
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
     Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * 
     Math.sin(dLon/2) * Math.sin(dLon/2); 
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 
    var d = R * c; 
    return d; 
} 

function test() { 
    var d1 = new Date(); 
    var lat1, lon1, lat2, lon2; 
    lat1 = -36; 
    lon1 = 174; 

    lat2 = lat1; 
    lon2 = lon1; 

    while (lat2 > -37) { 
    lat2 = lat2 - 0.001; 
    var stest = "lat1=" + lat1 + ",lon1=" + lon1 + ",lat2=" + lat2 + ",lon2=" + lon2 + "=" + gc(lat1, lon1, lat2, lon2); 

    } 
    var d2 = new Date(); 
    var stest = (d2.getTime() - d1.getTime())/1000.0 + "s"; 
    $("#lblTest").html(stest + "<BR/>" + $("#lblTest").html()); 

} 
+0

¿Qué función está causando el tiempo de espera? – Zakaria

+0

hola Zakaria necesito llamar a prueba() que simula el error en el código de producción porque luego llama a gc() hasta 1000 veces – ajayel

Respuesta

10

Si desea ejecutar una operación de larga ejecución en JavaScript y está llegando a algún punto cercano al límite de tiempo de ejecución del script impuesto por algunos navegadores, tendrá que dividir su función en varias partes, ejecutar una sola pieza, muy corto setTimeout(fn, 1) y luego ejecuta la siguiente pieza, etc. Haciéndolo de esta manera, puedes ejecutar el código durante horas porque da la posibilidad de procesar otros scripts y otros eventos. A veces se requiere una pequeña cantidad de reestructuración de código para poder hacer esto, pero siempre es posible con un poco de trabajo.

El concepto básico en pseudo-código sería el siguiente:

var state = {}; // set initial state 
var done = false; 

function doWork() { 
    // do one increment of work that will never get even close to the browser 
    // execution time limit 
    // update the state object with our current operating state for the next execution 
    // set done = true when we're done processing 
    if (!done) { 
     setTimeout(doWork, 1); 
    } 
} 

doWork(); 

En su código específico, usted podría hacer algo como esto. Puede procesar 100 puntos de latitud a la vez y luego hacer un corto setTimeout para hacer los siguientes 100 y así sucesivamente. Puedes ajustar ese número 100 a lo que sea que funcione mejor. Cuanto mayor sea el número, más hará en cada temporizador y mejor será el tiempo de ejecución general, pero cuanto más se acerque al límite de ejecución del script del navegador. El setTimeout mantiene vivo el navegador (el procesamiento de otros eventos) y evita que el límite de tiempo de ejecución de patadas en.

function test() { 
    var d1 = new Date(); 
    var lat1, lon1, lat2, lon2, done = false;; 
    lat1 = -36; 
    lon1 = 174; 

    lat2 = lat1; 
    lon2 = lon1; 

    function calcGC() { 
     var cntr = 0; 
     while (lat2 > -37 && cntr < 100) { 
      lat2 = lat2 - 0.001; 
      var stest = "lat1=" + lat1 + ",lon1=" + lon1 + ",lat2=" + lat2 + ",lon2=" + lon2 + "=" + gc(lat1, lon1, lat2, lon2); 
      cntr++; 
     } 
     // if we have more to go, then call it again on a timeout 
     if (lat2 > -37) { 
      setTimeout(calcGC, 1); 
     } else { 
      var d2 = new Date(); 
      var stest = (d2.getTime() - d1.getTime())/1000.0 + "s"; 
      $("#lblTest").html(stest + "<BR/>" + $("#lblTest").html()); 
     } 
    } 
    calcGC(); 
} 
+0

Muchas gracias por esta excelente explicación y ejemplo jfriend00 intentaremos esto en nuestra página CUANTO ANTES. ¡Maravilloso! – ajayel

+0

implementado y funciona muy bien gracias de nuevo jfriend00 – ajayel

1

Parece que Apple redujo el tiempo de espera de ejecución para javascript en iOS5. Esto probablemente se debió a las mejoras generales de velocidad en Mobile Safari y también a la inclusión del motor Nitro para UIWebViews.

+0

definitivamente parece ser, nuestro código funcionó bien y consistentemente en iOS4 – ajayel

4

Mi sensación es que hay un error en iOS5 Safari, porque una vez que he empezado a obtener estos errores , Los consigo por todas partes (incluida la página de búsqueda de Google para celulares), sin que se produzca un tiempo de espera/pausa visible. La eliminación de Safari y su reinicio solucionan el problema (hasta que vuelva a suceder, tal vez se trate de un tiempo de espera genuino que coloca a Safari en un estado dañado inicialmente).

¿Ha intentado matar a Safari a través del menú multitarea y reiniciarlo?

0

Yo también creo que es un error del navegador IOS5. Tenemos un problema similar. Tenemos una gran aplicación de RIA con muchos códigos JavaScript, y después de una actualización de página, el navegador comienza a lanzar excepciones de tiempo de espera. iOS4 no tenía este problema. Y una vez que la excepción comienza a suceder, va de mal en peor, hasta que el navegador se rompe por completo: otras páginas no relacionadas lanzan la excepción y se niegan a procesar.

Killing Safari y reiniciarlo hace que el problema desaparezca.

+0

hola VladH y Will Dean, nuestro error podría ser reproducido consistentemente incluso con un navegador nuevo y se ha ido completamente con el enfoque jfriend00s. Aunque, curiosamente, si dos ventanas de navegador (o web de pantalla completa) ejecutan el mismo código al mismo tiempo, obtenemos el error de javascript descrito en la pregunta original. – ajayel

+0

@VladH, ¿está usando window.setTimeout o window.setInterval en su aplicación? – illvm

+0

No, todavía estamos tratando de determinar dónde exactamente en nuestra aplicación está la pieza que causa el tiempo de espera: nuestra aplicación es amplia y altamente asincrónica. Sin embargo, incluso cuando logramos encontrar una solución alternativa, hay un problema mayor: una vez que estos errores de tiempo de espera comienzan a aparecer, Safari se rompe: uno actualiza la página unas pocas veces y ahora las secuencias de comandos JS que no tenían problemas dejan de funcionar incluso en sitios no relacionados en pestañas separadas. Nuestros scripts no deberían poder romper el navegador. Por cierto, acabamos de reproducir esto en el sitio de google maps, activando y desactivando la capa de satélite. – VladH

Cuestiones relacionadas