Javascript IOS5 "L'exécution de JavaScript a dépassé le délai d'attente"

Le test suivant est essentiellement ~ 1000 opérations mathématiques et fonctionne bien sur la plupart des navigateurs PC et Android, et iOS 4.x. Sur le safari iOS5 (iPhone 4 et iPad 2), nous obtenons "JavaScript: une erreur de l'exécution de JavaScript définie a dépassé le délai d'attente". Toute aide très appréciée merci.

/** 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()); } 

    Si vous souhaitez exécuter une opération longue durée en javascript et que vous obtenez n'importe où près de la limite de temps d'exécution du script imposée par certains navigateurs, vous devrez briser votre fonction en plusieurs pièces, exécuter une seule pièce, jusqu'à un setTimeout(fn, 1) très court setTimeout(fn, 1) , puis exécutez la pièce suivante, etc. … De cette façon, vous pouvez exécuter le code pendant des heures car il donne lieu à d'autres scripts et autres événements. Il faut parfois une petite quantité de restructuration de code pour pouvoir le faire, mais c'est toujours possible avec un peu de travail.

    Le concept de base en pseudo-code serait le suivant:

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

    Dans votre code spécifique, vous pourriez faire quelque chose comme ça. Vous pouvez traiter 100 points de latitude à la fois, puis faire un court setTimeout pour faire les 100 prochains et ainsi de suite. Vous pouvez ajuster ce nombre 100 à tout ce qui pourrait mieux fonctionner. Plus le nombre est élevé, plus vous faites sur chaque minuteur et le meilleur temps d'exécution global, mais plus vous rapprochez de la limite d'exécution du script du navigateur. SetTimeout maintient le navigateur en vie (traitement d'autres événements) et empêche le délai d'exécution de coups de pied.

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

    Je pense qu'il y a un bug dans le safari IOS5, car une fois que j'ai commencé à obtenir ces erreurs, je les achemine partout (y compris la page de recherche mobile de Google), sans délai / pause visible. Killing Safari et le redémarrage résolvent le problème (jusqu'à ce qu'il se reproduise), peut-être un véritable délai d'attente qui met le Safari dans l'état brisé initialement).

    Avez-vous essayé de tuer Safari via le menu multitâche et de le redémarrer?

    On dirait que Apple a réduit le délai d'exécution pour javascript dans iOS5. Cela s'explique probablement par l'amélioration générale de la vitesse dans Safari mobile et l'inclusion du moteur Nitro pour UIWebViews.

    Je pense aussi que c'est un bug de navigateur IOS5. Nous avons un problème similaire. Nous avons une grande application RIA avec beaucoup de code Javascript, et après une actualisation de la page, le navigateur commence à lancer des exceptions temporelles. IOS4 n'a pas eu ce problème. Et une fois que l'exception commence à se produire, elle va de mal en pire, jusqu'à ce que le navigateur soit complètement brisé: d'autres pages non liées jettent l'exception et refusent de les rendre.

    Killing Safari et le redémarrage font disparaître le problème.