JavaScript execution exceeded timeout

2019-04-07 19:56发布

问题:

  1. I am not doing a large chunk of computation in JS.
  2. Everything works fine on iPad iOS 5 in Safari until I added this code:

    var watchID = navigator.geolocation.watchPosition(updatePos,locationError,{maximumAge: 10000, frequency: 60000, enableHighAccuracy: true, timeout: 1000});
    
    function updatePos(position) {       
        if (position.coords.accuracy < accuracyThreshold) {                 
            $.post(websiteRoot + '/ReportDeviceLocation?rand=' + (Math.random() * Math.random()) + '&longitude=' + position.coords.longitude + '&latitude=' +position.coords.latitude);
    
        } else {
            console.debug("Location data is not accurate enough. Location not updated.");
        }
    }
    
  3. Then the web page worked for about 4 minutes and I get this error:

    JavaScript execution exceeded timeout.

  4. Then no JavaScript would load. None of the debug messages I inserted into my.js file would print. Only the above error.

  5. The error persists even after I left the page that generated this error, and opened other web pages under the same domain.

  6. I used try and catch, I used setTimeout function, but neither gave me the source of the error nor solved the problem.

I don't know what the problem is. It has been burning me for the entire day and will be burning me for the weekend.

回答1:

Surprisingly, when I used geolocation.getCurrentPosition, the error message stopped showing up. To replace watchPosition with getCurrentPosition, I use the function setInterval:

        function getLocation() {
            navigator.geolocation.getCurrentPosition(updatePos, locationError, { enableHighAccuracy: true, timeout: 10000 });
        }

        var intervalID = window.setInterval(getLocation, 10000);

This has worked out better than watchPosition because watchPosition sometimes does not follow rules(update location 8 times in 3 minutes despite the frequency is set to 10 minutes).

If the timeout still occurs, one would need to call clearInterval:

var geolocationID;
(function getLocation() {
     var count = 0;
     geolocationID = window.setInterval(
       function () {
            count++;
            if (count > 3) {  //when count reaches a number, reset interval
                window.clearInterval(geolocationID);
                getLocation();
            } else {
                navigator.geolocation.getCurrentPosition(updatePos, locationError, { enableHighAccuracy: true, timeout: 10000 });
            }
        },
        600000); //end setInterval;
})();


回答2:

Just as an addendum: This problem exists on the iPhones as well (not surprisingly) and is still not fixed. Even worse, if you exit (not kill) the browser, you get a battery drainer, within 12hrs the phone is dead. Unfortunately I need to rely on the watch since getCurrentPosition is by far not as accurate.

Once the bug sets in (after ~4min, as reported), an execution timeout error is reported exactly every second and the JS engine is dead. The problem is that it is NOT an execution timeout. That is the bug, even site reloads do not change it, stop/start of the watch does not help either. Only killing the browser (double-tap on the button, long tap on icon, then -) does the trick.

It seems that we are doomed until apple releases a fix...

Update: after more experimenting with this it seems the problem are XHR requests, maybe jquery specific, it seems there is some limit on those requests or no proper cleanup. The timeout error would pop up on any other site as well as soon as the first XHR is triggered. Before all JS runs fine.



回答3:

I struggled with the same problem and found a quite elegant solution.

The timeout errors occurred when I started my 'follow location mode' with navigator.geolocation.watchPosition and reloaded the page without stopping it. So I could fix this problem just by clearing the watcher when the user leaves the page.

$(window).unload(function(){
  window.navigator.geolocation.clearWatch(myWatchHandler);
});

Hope this helps!



回答4:

I am using watchPosition to post back my long, lat and most important speed. I got the same problem like users in this thread: Safari/Chrome on iOS killed the GPS feed (it wasn't the interval that stopped, I tested). Only by killing the browser (as in double click home button) I could make it work again for a couple of seconds. I tried everything, like clearing the interval but it didn't work. Then, later, I went outside and it kept on working! Went back inside and the GPS signal was gone. Since apps like RunKeeper kept on working inside I assumed that it would work inside as well, but that turned out to be wrong. If anybody has any questions, please feel free to ask.



回答5:

Maybe it's the Safari issue that blocks all getCurrentPosition while running watchPosition in another Tab or Website.



回答6:

I had a similar problem, and I also use html5 geolocation.

I have already implemented the suggested setInterval() solution. The same issue to still occurred, although taking a much longer time.

I did some experimentation by putting the following snippet in my code, just to 'pause' the code execution:

ms = 30000;
ms += new Date().getTime();
while (new Date() < ms){
}

The above snippet reliably generates a javascript execution timeout. I surreptitiously discovered that the next snippet will generate a timeout as well. But it seems that the browser is able to recover from the timeout. Don't ask me why. It just works. I hope that those affected can verify my findings.

ms = 30000;
ms += new Date().getTime();
while (new Date() < ms){
    if (new Date() %100 == 0){
        console.log('in while');
    }
}

So, the solution seems to be, trivial it may seem, that console.logs should be added to portions of the code which is called most often. I hope that this can be helpful (though I think it seems ridiculous too but it works for me)