requirejs加载脚本进度

时间:2013-03-22 23:42:03

标签: requirejs

冒险提出一个愚蠢的问题,我会尝试一下。

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

如果我的Google搜索中没有显示某些插件,我不想开始修改RequireJS来源。

感谢您的帮助。

3 个答案:

答案 0 :(得分:13)

可以显示微调器或进度指示器,但不能显示条本身。我可以获取requirejs的状态(当前正在加载或空闲),但不是加载/需要加载模块的%,因为它们的依赖关系在每个模块加载时都会被解析,但不会在开始时解析。

但是,无论如何,当用户等待时,至少有一个简单的微调器的页面要比空白页面好得多。

无需更改requirejs!所以..

假设我们有

文件require.conf.js
require.config({...})
require(["app"], function () { 

// main entry point to your hugde app's 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调用,通过depjs和所有其他人员传递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 {


    }


};

一个问题是:我们无法以某种方式计算出需要加载多少模块,因此我们无法计算加载进度的实际百分比。但是,至少,我们可以发现,无论我们是否正在加载某些内容(以及事件获取当前正在加载模块名称)并将其显示给紧张的用户

答案 1 :(得分:10)

自v 2.1.19起,RequireJS具有onNodeCreated配置属性。如果为其分配函数,则每次将<script>元素附加到文档以加载模块时,都会调用该函数。

该功能将通过nodeconfigmoduleNameurl参数提供。通过将事件侦听器附加到node,您可以检测脚本何时加载或无法加载。

现在您可以检测加载过程何时开始和停止,并可以使用该信息通知用户:

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&lt; 9您需要额外的代码来附加事件监听器。

注意:这仅适用于RequireJS直接请求的模块。插件(requirejs / text等)都使用自己的加载机制,不会触发onNodeCreated。有些会触发onXhronXhrComplete,所以您也可以处理它们:

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

答案 2 :(得分:8)

不,这是不可能的。 RequrieJs通过在DOM中创建新的脚本标记来加载模块并侦听load事件。开始和结束加载之间没有更新事件。所以这不是requireJs的限制,而是DOM。