Подтвердить что ты не робот

Requirejs load script прогресс

Рискуя спросить глупый вопрос, я попробую хотя бы.

Можно ли отображать индикатор прогресса, в то время как RequireJs загружает зависимости?

Например:

require(['jquery'], function($) {

    // Well, jQuery loaded in quite some time due to a low-speed connection
    //
    // Or maybe I wanted to show an overlay to prevent user of clicking on UI widgets until the load is complete
});

Я не хочу начинать изменять источник RequireJS, если там есть какой-то плагин, который не отображался в моих поисковых процессах Google.

Спасибо за вашу помощь.

4b9b3361

Ответ 1

Нет, это невозможно. RequrieJs загружает модуль, создав новый тег script в DOM и прослушивая событие загрузки. Нет событий обновления между начальной и конечной загрузкой. Поэтому это не ограничение requireJs, а DOM.

Ответ 2

Можно отобразить индикатор счетчика или индикатора прогресса, но не панель. Я мог получить статус requirejs (в настоящее время загружается или простаивает), но не% загруженных/необходимых для загрузки модулей, потому что их зависимости анализируются при каждой загрузке модуля, но не в начале.

Но, во всяком случае, страница с, по крайней мере, простым счетчиком, намного лучше, чем просто пустая страница, пока пользователь ждет.

Никаких изменений в requirejs не требуется! Так..

Предположим, что у нас есть файл require.conf.js с

require.config({...})
require(["app"], function () { 

// main entry point to your hugde app code 
});

и он загружается с помощью html с помощью

<script data-main="require.conf" type="text/javascript" src="bower_components/requirejs/require.js"></script>

Это стандартный сценарий requirejs. Добавьте индикатор в

<div id="requirejs-loading-panel">
    <div id="requirejs-loading-status"></div>
    <div id="requirejs-loading-module-name"></div>
</div>

Хорошо, позвольте догнать функцию requirejs, называемую require.onResourceLoad, и выполнить всю необходимую магию. Он будет вызываться requirejs при каждой загрузке модуля, передавая контекст requirejs с деревом депо и всем другим персоналом. Мы будем использовать контекст, чтобы узнать, требует ли что-либо requirejs что-то или нет. Я сделал это по расписанию по таймеру, потому что onResourceLoad() вызывается только при загрузке, а не при загрузке. Этот код необходимо добавить в require.js.conf:

require.onResourceLoad = function (context, map, depMaps) {


    var loadingStatusEl = document.getElementById('requirejs-loading-status'),
        loadingModuleNameEl = document.getElementById('requirejs-loading-module-name');
    var panel = document.getElementById('requirejs-loading-panel');

    if (loadingStatusEl && loadingModuleNameEl) {


        if (!context) { // we well call onResourceLoad(false) by ourselves when requirejs is not loading anything => hide the indicator and exit

            panel.style.display = "none";
            return;
        }

        panel.style.display = ""; // show indicator when any module is loaded and shedule requirejs status (loading/idle) check
        clearTimeout(panel.ttimer); 
        panel.ttimer = setTimeout(function () {


            var context = require.s.contexts._;
            var inited = true;
            for (name in context.registry) {
                var m = context.registry[name];

                if (m.inited !== true) {
                    inited = false;
                    break;
                }

            } // here the "inited" variable will be true, if requirejs is "idle", false if "loading"

            if (inited) {
                require.onResourceLoad(false);  // will fire if module loads in 400ms. TODO: reset this timer for slow module loading
            }

        }, 400)
        if (map && map.name) { // we will add one dot ('.') and a currently loaded module name to the indicator

            loadingStatusEl.innerHTML = loadingStatusEl.innerHTML += '.'; //add one more dot character
            loadingModuleNameEl.innerHTML = map.name + (map.url ? ' at ' + map.url : '');
        }
    } else {


    }


};

Одна из проблем: мы не можем каким-то образом выяснить, сколько модулей необходимо загрузить, поэтому мы не можем вычислить фактический процент загрузки. Но, по крайней мере, мы можем узнать, загружаем мы что-то или нет (и событие получает в настоящее время загрузку имени модуля) и покажите его нервному пользователю

Ответ 3

Так как v. 2.1.19 RequireJS имеет свойство onNodeCreated config. Если вы назначите ему функцию, эта функция будет вызываться каждый раз, когда элемент <script> добавляется к документу для загрузки модуля.

Функция будет снабжена аргументами node, config, moduleName и url. Подключив прослушиватели событий к node, вы можете обнаружить, когда загружен или не загружен script.

Теперь вы можете обнаружить, что процесс загрузки и остановки загрузки и может использовать эту информацию для уведомления пользователей:

require.config({
  /* ... paths, shims, etc. */
  onNodeCreated: function(node, config, moduleName, url) {
    console.log('module ' + moduleName + ' is about to be loaded');

    node.addEventListener('load', function() {
      console.log('module ' + moduleName + ' has been loaded');
    });

    node.addEventListener('error', function() {
      console.log('module ' + moduleName + ' could not be loaded');
    });
  },
});

Для IE < 9 вам понадобится дополнительный код для подключения слушателей событий.

Примечание: это работает только для модулей, запрошенных функцией RequireJS. Плагины (requirejs/text и такие) каждый используют свой собственный механизм загрузки и не запускают onNodeCreated. Некоторые триггеры onXhr и onXhrComplete, хотя вы также можете обрабатывать их:

require.config({
  /* ... paths, shims, etc. */
  config: {
    text: {
      onXhr: function(xhr, url) {
        console.log('file ' + url + ' is about to be loaded');
      },
      onXhrComplete: function(xhr, url) {
        console.log('file ' + url + ' has been loaded');
      }
    }
  }
});