Javascript 加载完成后分别渲染每个模块

Javascript 加载完成后分别渲染每个模块,javascript,requirejs,amd,Javascript,Requirejs,Amd,我有一个包含多个模块的应用程序,它们需要在加载完成后立即呈现。其思想是,无论其他模块的状态如何,每个模块都执行其专用的渲染功能 以下是主模块的实现: ;(function(doc, win, undefined) { 'use strict'; define(['module', 'domReady!'], function(main) { var modules = main.config().modules; while (modules.length)

我有一个包含多个模块的应用程序,它们需要在加载完成后立即呈现。其思想是,无论其他模块的状态如何,每个模块都执行其专用的渲染功能

以下是主模块的实现:

;(function(doc, win, undefined) {
   'use strict';

   define(['module', 'domReady!'], function(main) {
      var modules = main.config().modules;
      while (modules.length) {
         require([].concat(modules.shift()), function(module) {
            module.init();
         });
      }
   });

}(document, window));

看起来,尽管每个模块都应该在加载后立即渲染,但在所有模块完成加载之前,屏幕上不会显示任何内容。这会导致进入应用程序时出现延迟,并且不会给出应用程序已开始执行的指示。是什么导致了这种行为以及如何使应用程序的初始化尽可能顺利?

提供您想要的效果不是AMD语义的一部分。您唯一能保证的是,在加载回调附带的依赖项数组中列出的模块及其依赖项之前,传递给
require
的回调不会运行

RequireJS无法很好地控制浏览器向服务器发送请求的方式。例如,如果在您发出请求时,浏览器已经有太多的其他未决请求(对于样式表、图像或除您通过
require
请求的模块之外必须加载的其他内容),那么浏览器可能会决定延迟RequireJS的请求,直到较早的请求得到解决

在服务器端解析请求的方式也会影响按什么顺序发生的事情

然后是应用程序的结构。假设
main.config().modules
包含
['A','B','C']
。因此,您希望按顺序加载
A
B
C
,并尽快对它们进行初始化。然而,事实证明,所有这些模块也依赖于
jquery
。当RequireJS执行
A
时,它运行
define(['jquery],function($){…
。好的,现在必须提取
jquery
。在提取
jquery
时,很可能
B
C
也在等待它。因此RequireJS将执行
A
B
C
以及按顺序依次等待它们的回调。只有一个dependency这可能没什么大不了的,但如果您的模块依赖于大量其他通用模块,那么它会累加起来,最终结果是在加载通用模块时,您会得到明显的等待,然后看起来像是批执行
a
B
C

通过使用RequireJS自己的优化器或其他了解AMD模块的优化器,可以尝试将您的模块组合成有利于您寻找的结果的捆绑包。进行此类优化需要开发人员仔细分析应用程序的结构。在一般情况下,没有单一标志,即你只需打开它就可以得到你想要的结果。此外,如上所述,浏览器和服务器的工作方式可能会把事情搞砸


为了完整起见,我应该提到一件事。您可以强制进行顺序初始化,但仅在加载前一个模块后请求一个模块:

;(function(doc, win, undefined) {
   'use strict';

   define(['module', 'domReady!'], function(main) {
      var modules = main.config().modules;
      function next() {
        var name = modules.shift();
        if (name === undefined) {
          return;
        }

        require([name], function (module) {
          // When one module has loaded, we initiate the request for the
          // next one.
          next();

          // And init what we've got now.
          module.init();
        });
      }

      next();
   });
}(document, window));

然而,这里的代价是,
B
仅在加载了
A
之后才被请求,而在您的原始代码中,所有模块都会立即被请求。这可能会导致总初始化时间更长。

感谢您给出了一个非常深刻的答案!在我的应用程序中使用RequireJS库之前,加载时间es实际上更好,至少下载速度相对较快。我开始使用RequireJS的最大原因是为了确保我的应用程序在未来的增长中(特别是当依赖项和模块的数量越来越多时)是可维护的。我认为我的主要目标是缩短获取主要依赖项和开始初始化模块之间的延迟。至少要让我的“加载”模块加载并快速初始化,从而改善用户体验。