Как устранить потенциальное состояние гонки между двумя обработчиками загрузки скрипта - PullRequest
0 голосов
/ 07 января 2019

Я раздвоил некоторый код, который полагался на два таймера вместо обработчика 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, ни else, потому что upstaged.isRendered обновляется обработчиком showdown между ними. Должен ли я быть обеспокоен и вернуться к пути setInterval, который не будет зависеть от состояния гонки? Или есть другой способ, например, с помощью обещаний (не моя сильная сторона). Ранее я использовал обратный отсчет, ожидая возвращения нескольких вызовов Ajax, но похоже, что «временная зависимость» между двумя сценариями загрузки все равно будет существовать.

    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 голосов
/ 07 января 2019

Я решил аналогичную задачу через 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'))
...