简体   繁体   English

Javascript IOS5“ JavaScript执行超出超时”

[英]Javascript IOS5 “JavaScript execution exceeded timeout”

the following test is basically ~1000 math operations and works fine on most PC and android browsers, and iOS 4.x. 以下测试基本上是大约1000次数学运算,并且可以在大多数PC和android浏览器以及iOS 4.x上正常运行。 On iOS5 safari (iPhone 4 and iPad 2) we get "JavaScript: Error undefined JavaScript execution exceeded timeout". 在iOS5 Safari(iPhone 4和iPad 2)上,我们收到“ JavaScript:错误未定义的JavaScript执行超出超时”。 Any help greatly appreciated thanks. 任何帮助,非常感谢。

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

}

If you want to execute a long running operation in javascript and you are getting anywhere close to the script execution time limit enforced by some browsers, then you will have to break your function into multiple pieces, run one piece, to a very short setTimeout(fn, 1) and then execute the next piece, etc... Doing it this way, you can run code for hours because it gives other scripts and other events a chance to process. 如果要在JavaScript中执行长时间运行的操作,而您却接近某些浏览器所强制执行的脚本执行时间限制,则必须将函数分成多个部分,然后运行一次,直到很短的setTimeout(fn, 1) ,然后执行下一部分,依此类推。这样做,您可以运行几个小时的代码,因为它为其他脚本和其他事件提供了处理的机会。 It sometimes requires a minor amount of code restructuring to be able to do this, but it's always possible with a little work. 有时需要进行少量的代码重组就可以做到这一点,但是只需做一些工作就可以实现。

The basic concept in pseudo-code would be this: 伪代码的基本概念是这样的:

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

In your specific code, you could do something like this. 在您的特定代码中,您可以执行以下操作。 You can process 100 latitude points at a time and then do a short setTimeout to do the next 100 and so on. 您可以一次处理100个纬度点,然后执行一个简短的setTimeout来处理下一个100点,依此类推。 You can adjust that 100 number to whatever would work best. 您可以将100调整为最合适的数值。 The higher the number, the more you do on each timer and the better overall execution time, but the closer you get to the browser script execution limit. 该数字越大,您在每个计时器上执行的操作就越多,总体执行时间也越长,但是您越接近浏览器脚本执行限制。 The setTimeout keeps the browser alive (processing other events) and prevents the execution time limit from kicking in. setTimeout使浏览器保持活动状态(处理其他事件),并阻止执行时间限制。

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

My feeling is that there is a bug in IOS5 safari, because once I've started to get these errors, I get them all over the place (including the Google mobile search page), with no visible timeout/pause occurring. 我的感觉是IOS5野生动物园中存在一个错误,因为一旦开始出现这些错误,我就会到处都找到这些错误(包括Google移动搜索页),而不会发生可见的超时/暂停。 Killing Safari and restarting it fixes the problem (until it happens again - perhaps it's a genuine timeout which puts Safari into the broken state initially). 杀死Safari并重新启动它可以解决问题(直到再次发生-也许是真正的超时,最初使Safari进入了损坏状态)。

Have you tried killing Safari via the multitasking menu and restarting it? 您是否尝试过通过多任务菜单杀死Safari并重新启动它?

Sounds like Apple reduced the execution timeout for javascript in iOS5. 听起来像Apple减少了iOS5中JavaScript的执行超时。 This was probably due to general speed improvements in Mobile Safari and also the inclusion of the Nitro engine for UIWebViews. 这可能是由于Mobile Safari中总体速度的提高以及UIWebViews的Nitro引擎的加入。

I too think it's an IOS5 browser bug. 我也认为这是IOS5浏览器错误。 We've got a similar issue. 我们有一个类似的问题。 We have a large RIA application with lots of Javascript code, and after a page refresh the browser starts throwing timeout exceptions. 我们有一个带有大量Javascript代码的大型RIA应用程序,页面刷新后,浏览器开始抛出超时异常。 iOS4 didn't have this issue. iOS4没有这个问题。 And once the exception starts happening, it goes from bad to worse, until the browser gets totally broken: other unrelated pages throw the exception and refuse to render. 一旦异常开始发生,情况就会变得越来越糟,直到浏览器完全崩溃:其他不相关的页面引发异常并拒绝呈现。

Killing Safari and restarting it makes the problem go away. 杀死Safari并重新启动它可以解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM