Javascript IOS5 “Esecuzione JavaScript superato il timeout”

il seguente test è fondamentalmente ~ 1000 operazioni matematiche e funziona bene sulla maggior parte dei browser per PC e Android e iOS 4.x. Su Safari iOS5 (iPhone 4 e iPad 2) viene visualizzato “JavaScript: errore di esecuzione JavaScript non definito superato”. Qualsiasi aiuto molto apprezzato grazie.

/** 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 + "
" + $("#lblTest").html()); }

Se si desidera eseguire un’operazione di lunga durata in javascript e ci si avvicina al limite di esecuzione dello script imposto da alcuni browser, sarà necessario suddividere la funzione in più parti, eseguire un pezzo, in un setTimeout(fn, 1) molto breve setTimeout(fn, 1) e quindi eseguire il prossimo pezzo, ecc … Facendolo in questo modo, è ansible eseguire il codice per ore perché offre ad altri script e altri eventi la possibilità di elaborare. A volte richiede una piccola quantità di ristrutturazione del codice per poterlo fare, ma è sempre ansible con un po ‘di lavoro.

Il concetto di base in pseudo-codice sarebbe questo:

 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(); 

Nel tuo codice specifico, potresti fare qualcosa di simile. È ansible elaborare 100 punti di latitudine alla volta e quindi eseguire un breve setTimeout per eseguire i successivi 100 e così via. È ansible regolare quel numero di 100 per qualsiasi cosa potrebbe funzionare meglio. Maggiore è il numero, maggiore è il numero di volte su ciascun timer e il miglior tempo di esecuzione complessivo, ma più si avvicina al limite di esecuzione dello script del browser. Il setTimeout mantiene in vita il browser (elaborando altri eventi) e impedisce l’esecuzione del limite di tempo di esecuzione.

 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 + "
" + $("#lblTest").html()); } } calcGC(); }

La mia sensazione è che ci sia un errore nel safari IOS5, perché una volta che ho iniziato a ricevere questi errori, li rimando ovunque (inclusa la pagina di ricerca mobile di Google), senza che si verifichino timeout / pause visibili. Killing Safari e il riavvio risolvono il problema (fino a quando non accade di nuovo, forse è un timeout genuino che mette inizialmente Safari in stato di blocco).

Hai provato a uccidere Safari tramite il menu multitasking e riavviarlo?

Sembra che Apple abbia ridotto il timeout di esecuzione per javascript in iOS5. Ciò è probabilmente dovuto a miglioramenti della velocità generale in Mobile Safari e anche all’inclusione del motore Nitro per UIWebViews.

Anch’io penso che sia un bug del browser IOS5. Abbiamo un problema simile. Abbiamo una grande applicazione RIA con un sacco di codice Javascript, e dopo una pagina di aggiornamento il browser inizia a lanciare eccezioni di timeout. iOS4 non ha avuto questo problema. E una volta che l’eccezione inizia a verificarsi, va di male in peggio, fino a quando il browser non si rompe completamente: altre pagine non correlate lanciano l’eccezione e si rifiutano di eseguire il rendering.

Uccidendo Safari e riavviandolo il problema scompare.