【问题标题】:Running Q on page with Require.js使用 Require.js 在页面上运行 Q
【发布时间】:2014-11-25 00:31:36
【问题描述】:

我正在尝试在利用 Q 库的网页上运行小部件。不幸的是,该页面还使用嵌入 require.jsAddThis 小部件 并导致冲突。具体来说,当同时运行时,控制台会显示以下两条错误消息:

未捕获的 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>

【问题讨论】:

  • 一些源代码怎么样? RequireJS 配置?
  • 我找到了部分解决方案。通过注释掉 Q 中的 RequireJS else if 块(在 Montage Require 和 CommonJS 下),我可以在 RequireJS 旁边的全局命名空间中运行它而不会出现错误。但是,如果有人通过 RequireJS 加载 Q,这仍然会导致冲突。所以问题仍然存在,是否有一种模式可以将 Q(或任何其他库)包装在已知命名空间中的对象中?

标签: javascript namespaces requirejs shared-libraries q


【解决方案1】:

我会先说我不熟悉“AddThis”,并且不会称自己为 Require 专家,但我会尝试解决您在这种情况下遇到的层层问题.

首先,当 Q 找到 require 时,它​​不会将自己置于全局命名空间中,而只是使用 Q 模块调用 define。这会在 require 中创建一个匿名模块,通过使用该文件的路径调用 require 来加载该模块。这是可能在非浏览器环境中使用的模块的常见模式。当您注释掉该块时,它会进入“脚本”模块加载器,在其中创建 Q 模块的一个实例并将其设置为 self。在浏览器中,这(显然)是 window 的别名。

那么,我们如何在不注释掉 q.js 中的部分模块垃圾的情况下解决这个问题呢?

您应该能够使用 Require 的 shim configuration 将 Q 导出到全局范围,如下所示:

require.config({
    shim: {
        Q: {
            exports: "Q"
        }
    }
});

但这有两个问题。首先,您无法控制 require 配置,对吧?它由“AddThis”插件加载。其次,从 shim 配置中导出 Q 似乎对 Q 不起作用,可能是因为 Q 在内部使用“define”(Require 表示在内部使用“define”的脚本可能无法正确填充。这也可能是触发你的“不匹配的匿名定义()模块”错误)。奇怪的是,Q 的 github 上似乎没有任何其他关于这种缺乏 shim 能力的 SO 问题或问题。我不确定 Q 是否在做“错误”的事情,或者我只是疯了。也许对模块匀场有更多了解的人可以对此发表评论。

在任何情况下,您都不能在此处填充它。您应该能够执行以下操作:

if ( require ){
    require(['path/to/Q'],function(Q){ window.Q = Q; });
}

仅当 require 存在时才会显式要求 Q 并将其保存到 window 变量中,以便您可以在任何地方使用它。

但是,这也有一个问题。此处的“路径/到/Q”将相对于该需求配置中设置的任何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();
}

这完全未经测试,但它似乎可以工作!

【讨论】:

猜你喜欢
  • 2013-09-18
  • 2012-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-27
相关资源
最近更新 更多