lundi 7 janvier 2019

How to eliminate a potential race condition between two script onload handlers

I forked some code that was relying on two timers instead a script's onload handler. My first attempt eliminated one of the handlers, and made the other more robust by using setInterval, and shortened the time as well as it ran after one interval:

    isRendered: false,
    loadScript: function(src) {
        var s = document.createElement('script');
        var interval;

        s.type = 'text/javascript';
        s.async = true;
        s.src = src;
        s.onload = (function() {
            if (src === prettifyJs) {
                interval = setInterval(function() {
                    if (upstaged.isRendered) {
                        clearInterval(interval);
                        // Highlight any code out there
                        prettyPrint();
                    }
                }, 25);
            }
            if (src === showdownJs) {
                upstaged.render(upstaged.markdownContent);
                upstaged.isRendered = true;
                upstaged.afterRender();                 
            }
        });

        var head = document.getElementsByTagName('head')[0].appendChild(s);
    },

I've since devised a way to eliminate the second timer but it relies on a flag or another, function, value, and I'm concerned there could be a slim chance of a race condition if the condition within the prettifyJs handler executes neither the if nor else because upstaged.isRendered gets updated by showdown's handler between the two. Should I be concerned and go back to the setInterval way which won't be subject to a race condition? Or is there another way such as through using promises (not my forte). I've used a countdown before before when waiting for several Ajax calls to return, but this seems like the "temporal dependence" between the two onload scripts would still exist.

    isRendered: false,
    onPrettifyJsLoaded: function() {},
    loadScript: function(src) {
        var s = document.createElement('script');
        var interval;

        s.type = 'text/javascript';
        s.async = true;
        s.src = src;
        s.onload = (function() {
            if (src === prettifyJs) {
                if (upstaged.isRendered)  {
                    prettyPrint();
                }
                else {
                    upstaged.onPrettifyJsLoaded = function() {prettyPrint()};
                }
            }
            if (src === showdownJs) {
                upstaged.render(upstaged.markdownContent);
                upstaged.isRendered = true;
                upstaged.onPrettifyJsLoaded();
                upstaged.afterRender();                 
            }
        });

        var head = document.getElementsByTagName('head')[0].appendChild(s);
    },

Aucun commentaire:

Enregistrer un commentaire