我正在尝试在利用 Q库的网页上运行小部件。不幸的是,该页面还使用嵌入 require.js 的 AddThis小部件并导致冲突。具体来说,当一起运行时,控制台中会显示以下两条错误消息:
未捕获的ReferenceError:Q未定义
未捕获的错误:匿名的define()模块不匹配
不幸的是,我无法控制AddThis小部件的使用。但是,我确实可以使用Q控制嵌入式应用程序。是否有一个JavaScript模式可以实现命名空间Q库,以便它不会与require.js冲突?
这是一个演示问题的简单示例:
<!doctype html />
<html>
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.15/require.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/q.js/0.9.2/q.min.js"></script>
</head>
<body>
<script>
var called = function() {
var deferred = Q.defer();
console.log("Q called successfully");
deferred.resolve();
return deferred.promise;
}
Q.fcall(called);
</script>
</body>
</html>
答案 0 :(得分:2)
我将在前言中说我不熟悉“AddThis”,并且不会称自己为“需要”的专家,但我将尝试解决您在这种情况下遇到的各种问题
首先,当Q发现require时,它不会将自己置于全局命名空间中,而只是使用Q模块调用define
。这将在require中创建一个匿名模块,该模块通过使用该文件的路径调用require
来加载。这是可能在非浏览器环境中使用的模块的常见模式。当你注释掉那个块时,它会转到“脚本”模块加载器,在那里它创建一个Q模块的实例并在self
上设置它。在浏览器中,这显然是窗口别名。
那么,我们如何解决这个问题而不在q.js中注释掉模块垃圾的部分内容?
您应该能够使用Require的shim configuration将Q导出到全局范围,如下所示:
require.config({
shim: {
Q: {
exports: "Q"
}
}
});
但这有两个问题。首先,你无法控制require配置,对吧?它由“AddThis”插件加载。其次,从shim配置中导出Q对Q来说似乎不起作用,可能是因为Q在内部使用“define”(要求说内部使用“define”的脚本可能没有正确填充。这也可能是触发你的“匿名的define()模块“错误”不匹配。奇怪的是,在Q的github上似乎没有任何其他SO问题或问题关于这种缺乏补偿能力的问题。我不确定Q是做错了什么还是我疯了。也许对模块垫片有更多了解的人可以对此发表评论。
无论如何,你不能在这里垫片。你应该可以这样做:
if ( require ){
require(['path/to/Q'],function(Q){ window.Q = Q; });
}
如果需要存在,这将明确要求Q并将其保存到窗口变量中,以便您可以在任何地方使用它。
然而,这也有问题。这里的“path / to / Q”将相对于该require配置中设置的任何baseUrl。所以,如果“AddThis”将baseUrl设置为该插件的一些奇怪路径,那么你很难找到Q,那么你可能必须解决这个问题。
您可以使用Require的multiversion功能设置自己的配置,指定您自己的baseUrl:
if ( require ){
var myRequire = require.config({
baseUrl: '/my/local/root',
paths: {
Q: 'path/to/Q'
}
});
myRequire(['Q'],function(Q){
window.Q = Q;
bootstrapMyApp();
});
}
else {
bootstrapMyApp();
}
这是完全未经测试的,但似乎它可能有效!