间歇性的 RequireJS 加载错误

17

我有一个使用RequireJS的相当大的Backbone.js项目。随着项目规模的增长(这里的“规模”指的是单独模块文件的数量),偶发性错误开始出现。大多数情况下,这是一个对象错误:

Uncaught TypeError: object is not a function

偶尔会抱怨没有加载模块。

一旦通过r.js优化器运行项目,这些错误就会消失。这些错误只会在RequireJS加载单个模块时发生。

这就引出了我的问题 - 当模块数量达到一定数量时,RequireJS是否开始出现模块加载时间问题?


1
我怀疑这不是RequireJS的问题,而是与浏览器相关的问题。它是否在不同的浏览器中都无法正常工作?RequireJS是否记录了任何问题,例如在加载脚本时超时,输出到控制台? - Lucero
我在Chrome中看到它最多,但我也看到它在Firefox中发生过。没有RequireJS日志或错误。发生错误的情况是当我尝试实例化从已加载模块导出的Javascript函数(原型)时。它会抛出异常,因为该模块似乎没有正确加载,因为Javascript无法将其识别为函数。这就是错误实际发生的时候 - 这只是有时发生。其余时间,代码执行得非常好。无论如何,都没有RequireJS超时错误。 - redhotvengeance
1
对我来说,这绝对听起来像是同步/竞争条件问题。我也参与了一个非常大的Backbone项目,RequireJS方面从未发生过任何降级。 - ZenMaster
是的 - 正如我所说,这个问题是间歇性的,所以大部分时间一切都运行得非常好。这就是让我困惑的地方 - 代码是好的。但更具体地说,该模块返回一个函数,该函数有多个函数添加到其原型中。为了清晰起见,该模块是编译过的CoffeeScript。因此,该模块返回的是一个CoffeeScript“类”,但是CoffeeScript类只是一个带有其原型的函数。 - redhotvengeance
1
@Ben 好的建议 - 不幸的是,它们并不适用于我的情况。RequireJS 是我进入这个应用程序的唯一入口。此外,在你的情况下,即使经过优化,应用程序也会失败,而我的应用程序不会。在运行 r.js 优化器后,它从未抛出过这些错误。也没有抛出任何模块加载超时错误。非常奇怪和令人沮丧。 - redhotvengeance
显示剩余7条评论
4个回答

9

5

我在过去几天遇到了很多次的一个bug。加载一个模块可能会导致应用程序中不相关的另一个模块在之前运行良好的地方变为未定义。我经常使用RequireJS - 这不是脚本加载或循环依赖问题。起初,我最常遇到的错误是在需要迭代很多次(1800+)的二级视图中要求文本文件时:

domReady -calls-> new View1() -iterates-> new SubView() -depends-> text!template
         -calls-> new View2() --> undefined!

这会导致其他完全无关的模块变得未定义。我曾经通过将 SubView 功能整合到 View 模块中来解决这个问题。
domReady -calls-> new CombinedView1() -depends-> text!template
         -calls-> new View2() --> ... all good ...

随着项目的增长,我又遇到了问题,需要想办法解决。当我加入更多模块时,以前定义的模块会在随机位置变为未定义状态。Require没有抛出任何错误,浏览器也没有。我也没有使用CoffeeScript或类似的东西。
我花了一些时间创建了一个应用程序版本,该版本具有相同的模块和依赖结构,并且将依赖视图、模型和集合放在桩中。这个版本完全可以正常工作,所以我只能认为存在某种内存问题?然而,Chrome也没有抛出任何错误。
我认为下一步将是通过添加一些消耗内存的循环来填充我的骨架应用程序,并查看会发生什么:我会告诉您结果如何。
使用Require v2.0.1,因此没有顺序插件 - 依赖项和包都使用shim配置指令进行配置。 加载的非AMD模块:
- Backbone - Underscore - jQuery - Mustache - Leaflet - Bootstrap 附言:如果这不是正确的地方,请谅解。我认为这应该是一条评论,但实在找不到评论按钮。
更新:此依赖结构会一直出现问题。
Main
  - View 1
      - text!...
      - View 2
         - text!...

替换文本为空字符串每次都可以正常工作:
Main
  - View 1
      - View 2

那么为什么等待文本加载会导致视图1变为未定义,而它在主模块中被明确设置为依赖项?毕竟,在所有依赖项加载完成之前,主模块不应该被调用吗?

1
我遇到了完全相同的问题。也可以参考https://groups.google.com/forum/?fromgroups#!topic/requirejs/Eym3R08Bmmg - Steve Beer
显然,在视图1中也需要View 2的text!...依赖项才能使模块再次正确加载。虽然不太美观,但它确实有效。 - Steve Beer
很高兴听到我不是疯了——如果问题是间歇性的,那显然不可能是循环依赖问题。显然有更深层次的问题。我也会关注你开启的Google Groups线程,@SteveBeer。 - redhotvengeance

5

我最近几天一直在处理同一个问题,这是我找到的解决方法:

显然,通过text.js插件要求模板的嵌套依赖结构可能会导致竞争条件,从而使得requirejs认为顶级模块已经就绪,但实际上并没有。我只有在存在多个这种类型的嵌套模块依赖结构时才遇到了这个问题:

Router
  -> View1
    -> text!.../view1.html
    -> View2
      -> text!.../view2.html
  -> View3
    -> text!.../view3.html
    -> View4
      -> text!.../view4.html
  -> View5
    -> text!.../view5.html
    -> View6
      -> text!.../view6.html
  -> View7
    -> text!.../view7.html
    -> View8
      -> text!.../view8.html

有了这个结构,当路由器尝试实例化视图时,我遇到了诸如“View1不是构造函数”的类型错误。

在顶级视图中要求嵌套视图的模板解决了我的问题:

Router
  -> View1
    -> text!.../view1.html
    -> text!.../view2.html
    -> View2
      -> text!.../view2.html
  -> View3
    -> text!.../view3.html
    -> text!.../view4.html
    -> View4
      -> text!.../view4.html
  -> View5
    -> text!.../view5.html
    -> text!.../view6.html
    -> View6
      -> text!.../view6.html
  -> View7
    -> text!.../view7.html
    -> text!.../view8.html
    -> View8
      -> text!.../view8.html

我不太清楚require.js的工作原理,但对我来说,这似乎像是当父模块的某个“准备就绪”标志设置时,这些嵌套的text!调用并不会被考虑。


是的,这看起来就是导致问题的原因。我也使用了相当多的文本调用,所以问题似乎就出在那里。 - redhotvengeance

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接