使用 Require.js 在页面上运行 Q [英] Running Q on page with Require.js

查看:91
本文介绍了使用 Require.js 在页面上运行 Q的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to run a widget on a web page that leverages the Q library. Unfortunately, the page also uses the AddThis widget which embeds require.js and is causing a conflict. Specifically, when run together the two following error messages are displayed in the console:

未捕获的引用错误:未定义 Q
未捕获的错误:不匹配的匿名定义()模块

Uncaught ReferenceError: Q is not defined
Uncaught Error: Mismatched anonymous define() module

不幸的是,我无法控制 AddThis 小部件的使用.但是,我确实可以使用 Q 控制嵌入式应用程序.是否有可以实现 Q 库命名空间的 JavaScript 模式,以便它不会与 require.js 冲突?

Unfortunately, I don't have control over the use of the AddThis widget. However, I do have control over the embedded application using Q. Is there a JavaScript pattern that I can implement to namespace the Q library so that it will not conflict with require.js?

这是一个演示问题的简单示例:

Here is a simple example that demonstrates the problem:

<!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>

推荐答案

我先说我不熟悉AddThis",也不会称自己是 Require 方面的专家,但我会尝试解决您在这种情况下遇到的多层问题.

I'll preface this by saying I'm not familiar with "AddThis", and wouldn't call myself an expert on Require, but I'll try to work through the layers of problems you've got in this situation.

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

First, when Q finds require, it doesn't put itself in the global namespace, but just calls define with the Q module. This creates an anonymous module within require which is loaded by calling require using the path of that file. This is a common pattern for modules that might be used in non-browser environments. When you comment out that block, it goes down to the "script" module loader, where it creates an instance of the Q module and sets it on self. In the browser, this is (apparently) aliased to window.

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

So, how do we solve this problem without commenting out parts of the module junk in q.js?

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

You SHOULD be able to use Require's shim configuration to export Q to the global scope, which would look like this:

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

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

But there's 2 problems with this. Firstly, you're not in control of the require config, right? It's loaded by the "AddThis" plugin. Secondly, exporting Q from a shim config doesn't even seem to work for Q, possibly because Q uses "define" internally ( Require says that scripts using "define" internally might not be shimmed properly. This might also be what's triggering your "Mismatched anonymous define() module" error ). It's weird that there doesn't seem to be any other SO questions or issues on Q's github about this lack of shim-ability. I'm not sure if Q is doing something "wrong" or I'm just crazy. Maybe someone who knows a little more about module shimming could comment on that.

无论如何,你不能在这里填充它.你应该能够做这样的事情:

In any case, you can't shim it here. You should be able to do something like this:

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

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

This will explicitly require Q only if require exists and save it to the window variable so you can use it wherever.

不过,这也有问题.这里的path/to/Q"将相对于任何 baseUrl 设置在那需要的配置.因此,如果AddThis"将 baseUrl 设置为该插件的某个奇怪路径,而您很难在 Q 上找到该路径,那么您可能必须解决该问题.

However, this also has a problem. The "path/to/Q" here will be relative to any baseUrl set in that require's config. So, if "AddThis" is setting the baseUrl to be some weird path for that plugin where it's hard for you to get at Q, then you might have to solve that problem.

您可以使用 Require 的 multiversion 功能来设置您自己的配置指定您自己的 baseUrl:

You might be able to use Require's multiversion ability to set your own config where you specify your own 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();
}

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

This is completely untested, but it seems like it might work!

这篇关于使用 Require.js 在页面上运行 Q的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆