requirejs load script progress

天涯浪子 提交于 2019-12-18 14:53:29

问题


Risking of asking a stupid question I will give it a try though.

Is it possible to display a progress indicator while RequireJs is loading dependencies?

For example:

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

I don't want to start modifying the RequireJS source if there's some plugin out there which didn't show up in my Google searches.

Thanks for all your help.


回答1:


No, this isn't possible. RequrieJs loads the module by creating a new script tag in the DOM and listens to the load event. There are no update events in between start and end loading. So it's not a limitation of requireJs but the DOM.




回答2:


It is possible to display a spinner or progress indicator, but not the bar itself. I could get status of requirejs (currently loading or idle), but not the % of loaded/needed to be loaded modules, because their dependencies are parsed upon every module load, but not at the beginning.

But, anyway, page with, at least, a simple spinner, is much better, than just blank page, while user waits.

No changes to requirejs needed! So..

Assume we have file require.conf.js with

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

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

and it is loaded by html using

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

This is standard requirejs scenario. Let's add the indicator to the

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

Ok, let's catch up requirejs's function called require.onResourceLoad and do all the magic needed. It will be called by requirejs upon every module load, passing the requirejs's context with dep tree and all other staff. We will use context to find out, whether requirejs is loading something or not. I did it in scheduled timer call, because onResourceLoad() is called only while loading, not when it is done loading. This code needs to be added to 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 {


    }


};

One problem is: we cannot somehow figure out how much modules are needed to load, so we can't compute the actual % of loading progress. But, at least, we can find out, whether we're loading something or not (and event get currently loading module name) and show it to a nervous user




回答3:


Since v. 2.1.19 RequireJS has onNodeCreated config property. If you assign a function to it, that function will be called each time a <script> element is appended to a document to load a module.

The function will be provided with node, config, moduleName, and url arguments. By attaching event listeners to the node, you can detect when the script has been loaded or failed to be loaded.

Now you can detect when loading process starts and stops and can use that information to notify users:

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

For IE < 9 you'd need additional code to attach event listeners.

Note: this only works for modules requested by RequireJS directly. Plugins (requirejs/text and such) each use their own loading mechanism and do not trigger onNodeCreated. Some trigger onXhr and onXhrComplete though, so you can handle them too:

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


来源:https://stackoverflow.com/questions/15581563/requirejs-load-script-progress

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!