Archive

Posts Tagged ‘IFrame’

Fix: javascript location.hash throttling issue with IFrame

I had implemented a simple (and most importantly working in older browsers too) way of communication between an IFrame and its parent page via location.replace(“#” + hash), which doesn’t add entries to history like location.hash=… does, and the onhashchange event, when I noticed Edge-Chromium was throwing a “Throttling navigation to prevent the browser from hanging.” error and the lon/lat fields I had on my test page wheren’t updating anymore when I was dragging quickly for a while my location picker marker on an OpenLayers map. If I released the marker and tried after a sec it was starting working again.

image

     

since the URL shown in the error message redirects to some page that has permission denied, I looked up a discussion that explained the “–disable-ipc-flooding-protection” Chromium switch to turn off that protection, however I was not having any loop in my code that was mentioned in that discussion as probable cause.
https://stackoverflow.com/questions/55925936/angular-7-throttling-navigation-to-prevent-the-browser-from-hanging

On Firefox there was a similar error but with other message:

image

Searching about it I read about the “debouncing” concept (to avoid flooding some API with consequtive requests too fast/often) at

https://stackoverflow.com/questions/45236692/angular-and-observale-how-to-avoid-multiple-requests-to-api-within-a-given-time

and

https://stackoverflow.com/questions/35991867/angular-2-using-observable-debounce-with-http-get

And ended up finding a simple implementation of it at

https://medium.com/@griffinmichl/implementing-debounce-in-javascript-eab51a12311e

that I adapted to run in older browsers (like IE11) too:

function debounce(func, wait) {
  var timeout;
  return function() {
    var context = this;
    var args = arguments;
    clearTimeout(timeout); //clear previous scheduled execution if still pending
    timeout = setTimeout(function() { func.apply(context, args); }, wait);
  }
}

function setLocationHash(hash) {
    window.location.replace("#" + hash); //don’t set window.location.hash directly, adds entries to browser history
}

setLocationHashDebounced = debounce(setLocationHash, 20);
    //this will make sure any setLocationHash calls that occur within 20msec replace any pending ones (all are timed to execute in steps of 20msec)

//…

function markersUpdated(otherLocations) { //callback
    theOtherLocations = otherLocations;
    if (theOtherLocations.length > 0) {
        var hash = theOtherLocations[0].toString();
        setLocationHashDebounced(hash);
    }
}

function hashChanged() {
    var hash = window.location.hash.substring(1);
    if (hash.length > 0) {
        var hashParts = hash.split(‘,’);
        if (hashParts.length >= 2){
            var location = [hashParts[0], hashParts[1]]; //[lon, lat]
            map_addOtherMarker(location); //Note: this will just move selected marker if existing and otherLocations.length = _maxOtherLocations > 0
             if (hashParts.length >= 3 && hashParts[2] == "zoom")
                 zoomToLocation(location);
        }
    }
}

%d bloggers like this: