Running Q on page with Require.js

可紊 提交于 2021-01-29 05:17:41

问题


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:

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

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>

回答1:


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.

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.

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

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"
        }
    }
});

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; });
}

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

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.

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!



来源:https://stackoverflow.com/questions/27116780/running-q-on-page-with-require-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!