jQuery UI API在使用LABjs时无法正确加载

13

我最近在SharePoint Webparts(2010)中使用LABjs来加载脚本。这样做的主要原因是为了避免在同一页上添加多个Webparts时重复加载同一个库(例如jqueryjquery.ui)。这样每个Webpart都可以单独指定其依赖项,而不需要监控其他已添加或可能添加的Webpart。

LABjs和另一个包含脚本链的文件通过<script>标签在Webpart标记底部加载。

大多数情况下,Javascript执行没有任何问题。但是偶尔会抛出异常,显示TypeError: $(...).button is not a function

即使页面上只有一个Webpart,这也会发生,并且似乎与浏览器无关(在FireFox 38、Chrome 43和IE 11/IE 8(强制页)中进行了测试)。

脚本链如下所示(为清晰起见已编辑):

$LAB.setOptions({Debug:true})
.script("../js/jquery-1.11.3.min.js").wait()
.script("../js/jquery-migrate-1.2.1.min.js").wait()
.script("../js/jquery-ui.min.js").wait()
.script("../js/core.js")
.wait(function(){ 
    jQuery(function() {
        init();     // The jQuery UI .button() call
    });
})
.script("../js/jquery.multiselect.min.js").wait()
.script("../js/jquery.multiselect.filter.min.js")
.script("../js/rte/jquery.rte.js").wait()
.script("../js/rte/jquery.rte.tb.js")
.script("../js/rte/jquery.ocupload-1.1.4.js")
.wait(function () {
    jQuery(function() {
        // Some DOM-dependant code lives here
    });
});

这是调试器输出的内容(已经进行了编辑以便更清晰明了):

start script load (ordered async): ../js/jquery-1.11.3.min.js
start script load (ordered async): ../js/jquery-migrate-1.2.1.min.js
start script load (ordered async): ../js/jquery-ui.min.js
start script load (ordered async): ../js/core.js
start script load (ordered async): ../js/jquery.multiselect.min.js
start script load (ordered async): ../js/jquery.multiselect.filter.min.js
start script load (ordered async): ../js/rte/jquery.rte.js
start script load (ordered async): ../js/rte/jquery.rte.tb.js
start script load (ordered async): ../js/rte/jquery.ocupload-1.1.4.js
script execution finished: ../js/jquery-1.11.3.min.js
script execution finished: ../js/jquery-migrate-1.2.1.min.js
script execution finished: ../js/jquery-ui.min.js
script execution finished: ../js/core.js
$LAB.wait() executing: function (){ jQuery(function() { init(); }); }
$LAB.wait() error caught:  TypeError: $(...).button is not a function
    ...
script execution finished: ../js/jquery.multiselect.min.js
script execution finished: ../js/jquery.multiselect.filter.min.js
script execution finished: ../js/rte/jquery.rte.js
script execution finished: ../js/rte/jquery.rte.tb.js
script execution finished: ../js/rte/jquery.ocupload-1.1.4.js
$LAB.wait() executing: function () {
        jQuery(function() {
            ...
        });
    }
$LAB.wait() error caught:  TypeError: $(...).multiselect is not a function
    ...

这个错误几乎总是伴随着jquery.ui库漫长的加载时间。

同时,通过调试器的输出清晰地表明,在.button()调用之前已经完成执行。

我一直在为此而苦斗,非常感谢任何帮助/见解,以了解问题可能是什么,并如何修复。我一直在查阅LABjs文档,看是否有我做错了什么的线索,但似乎没有什么结果。


注意: 头部确实存在一个对jquery<script>引用,然而这个引用不能被移除(我无法访问主页面),并且我已经尝试将jquery从链中删除,但没有效果。


编辑: 有人认为问题可能是SharePoint服务器位于负载均衡器后面,这可能是jquery.ui库加载时间异常长的原因。虽然这是一种可能性,但我不知道为什么会影响LABjs的加载/执行功能。

---

更新

经过一番挖掘,我发现由于某种原因,jquery.ui库绑定到了jquery而不是我的代码所期望的$。为了尝试修复这个问题,在core.js中我创建了一个变量core.$,用jQuery.noConflict()实例化它,并将我的DOM相关代码封装在其中。

(function ($) {
    ...
})(core.$);

并将 .script(".../js/core.js") 的调用移动到链的末尾(以确保所有插件都正确回滚)。

虽然这没有解决问题,但出现次数已经降至大约50分之1。


这要看情况。如果页面上只有一个这样的 WebPart,那么是的,使用 <script> 标签同步加载库不会导致错误。 - LdTrigger
这听起来像是一个竞争条件。有可能在DOM准备就绪之前,有时会调用脚本或出现类似的情况吗? - John Hascall
理论上,jQuery 调用应该确保脚本内容绑定到 DOM 就绪事件。 - LdTrigger
@LdTrigger 你真的需要使用LABjs吗? - Buzinas
@Buzinas 这是我发现的最强大的库,可以动态加载JavaScript文件,同时防止Web部件之间的重复加载。即使您建议其他东西 - 请务必这样做 - 在这一点上,我更加好奇为什么会发生这种情况,而不是解决我的具体问题。 - LdTrigger
显示剩余4条评论
1个回答

1

@LdTrigger:“此外,当不指向负载均衡器时,错误似乎不会发生。” 这告诉你的解决方案不在代码中。请尝试使用“持久连接”/“粘性会话”,这很可能是因为您没有足够的“权限”从另一台服务器获取文件内容,因为它们都在负载均衡器后面。


系统管理员刚刚告诉我,生产环境使用相同的连接设置,而错误仅在开发环境中发生,因此这似乎不太可能。 - LdTrigger
但是,既然您说只有在负载均衡器起作用时才会出现这种情况,那么就存在差异,您的环境可能相同,但这并不意味着负载均衡器执行相同的操作。我可以百分之百确定,当代码作为独立系统运行时,您无法通过编写代码来解决任何问题。因此,您的防火墙/负载均衡器、内部网络将始终是问题的原因,解决方案是开始记录所有调用。如有必要,请检查您的网络选项卡,并请持久化调用并查看您的结果,并比较开发和生产的“端点”,然后查看所有内容。 - Tobias Hagenbeek
请确保来自相同调用的响应匹配,如果失败,请尝试检查您的开发人员是否可以指向生产依赖项并查看是否可以使其正常工作。 - Tobias Hagenbeek

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