如何消除两个脚本加载处理程序之间的潜在竞争条件

时间:2019-01-07 17:57:29

标签: javascript if-statement promise onload race-condition

我派生了一些依赖两个计时器而不是脚本的onload处理程序的代码。我的第一次尝试消除了其中一个处理程序,并通过使用setInterval使另一个处理程序更加健壮,并缩短了时间并使其间隔了一个时间:

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

此后,我设计了一种消除第二个计时器的方法,但是它依赖于标志或其他函数,值,而且我担心如果prettifyJs处理程序中的条件发生竞争的可能性很小因为if会在两个之间的摊牌处理程序中更新,所以不会执行elseupstaged.isRendered。我应该担心并返回不会受到竞争条件影响的setInterval方法吗?或者还有另一种方式,例如通过使用诺言(不是我的专长)。在等待几个Ajax调用返回之前,我已经使用了倒数计时,但是这似乎在两个onload脚本之间仍然存在“时间依赖性”。

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

1 个答案:

答案 0 :(得分:0)

我通过Promises解决了类似的任务:

var loadScriptDependence = new Promise((resolve, reject) => {
        let scr = document.createElement('script');
        scr.type = "text/javascript";
        scr.async = true;
        scr.src = `/script/dependence.js`;
        document.getElementsByTagName('head')[0].appendChild(scr);
        scr.onload = (() => resolve(true));
        scr.onerror = () => reject(Error('Error loading dependence.'));
    });

var loadDependedScript = new Promise((resolve, reject) => {
        let scr = document.createElement('script');
        scr.type = "text/javascript";
        scr.async = true;
        scr.src = `/script/depended.js`;
        document.getElementsByTagName('head')[0].appendChild(scr);
        scr.onload = (() => resolve(true));
        scr.onerror = () => reject(Error('Error loading depended.'));
    });

loadScriptDependence
  .then(() => loadDependedScript)
  .then(() => doSomething())
  .catch((err) => console.error('Error occured'))