How to load Q library with Require.js?

我怕爱的太早我们不能终老 提交于 2020-01-04 05:41:13

问题


My library use kriskowal/Q promises library and now I'm trying to load (with requirejs) application that use my library so I put all paths and shims and my requirejs.config section looks like this:

requirejs.config({
    baseUrl: './',
    catchError: false,
    paths: {
        beril: '../engine/build/src/bundle',
        lodash: 'bower_components/lodash/lodash',
        three: 'bower_components/three.js/build/three',
        q: 'bower_components/q/q',

    },
    shim: {
        lodash: {
            exports: '_'
        },
        three: {
            exports: 'THREE'
        },
        q: {
            exports: 'Q'
        },
        beril: {
            deps: ['lodash', 'three', 'q'],
            exports: 'beril'
        },
    }
});

After this I suppose variables THREE, _ and Q to be defined in global space. Now I'm loading and runinng application with this simple line:

require(['beril', 'js/stepbystep/' + $stateParams.page + '/app'], (beril, app) => app());

but then I'm getting error: ReferenceError: Q is not defined even though I can see in Chrome's network inspector that Q library have been loaded.

Also all the rest dependencies (THREE and _) are defined. Seems like requirejs`s shim does not work for this library. Can it be or am I missing something?

So what am I'm doing wrong and how should I deal with this situation?


回答1:


I found solution and it was to add init function to my library's shim and then add Q as global object manually so my shim section now looks like this:

shim: {
    lodash: {
        exports: '_'
    },
    three: {
        exports: 'THREE'
    },
    q: {
        exports: 'Q'
    },
    beril: {
        deps: ['lodash', 'three', 'q'],
        exports: 'beril',
        init: function(lodash, three, q){
            window.Q = q;
        }
    },
}

however I don't clearly understand why it does not work without this and are there better ways to deal with this situation.




回答2:


There are a few problems with your configuration. For one thing, you have unnecessary shim configurations. I installed lodash just now (with bower install lodash) and searched its code. It calls define. So you must not set a shim for it. RequireJS won't give you an error but you will get undefined behavior. The same is true of Q: it calls define so, no shim for it. Last I checked, THREE needs a shim.

The fact that Q calls define is also why it does not leak the symbol Q into the global space. It acts like a well-behaved AMD-module.

Ok, so how can we get Beril to find Q? Your solution works but I find it slightly iffy. The problem is that init is executed after the shimmed module is loaded. As long as Beril refers to Q only in the body of functions to be executed later, it will work. And I guess this is how Beril works now. However, if a new version of Beril needs to refer to Q when the file that contains Beril is first executed, it will fail because Q does not exist yet.

One way to work around the problem that is future-proof is to use map and some glue. Keep your shim for beril but remove the init. Define a module named q-glue:

define(['q'], function (Q) {
    window.Q = Q;
    return Q;
});

And declare this map in your configuration:

map: {
    beril: {
        q: "q-glue"
    }
}

This says "when q is requested from beril load q-glue instead." By doing this, window.Q will be defined before Beril is loaded.

I take it you are the author of Beril. I urge you to make your library AMD-compatible so as to spare users of your library having to go through configuration pains to get it working with AMD-loaders (like RequireJS).




回答3:


It worked for me after I downgraded to version 0.9 up until 1.0.1 as mentioned in the readme. The current version 2.0.2 has significant braking changes as mentioned by Kris Kowal here.

I didn't have the need to set the global variable as the older version checks the environment and does so if loaded before require.




回答4:


You need to add q to require()...

require(['beril', 'q', 'js/stepbystep/' + $stateParams.page + '/app'], (app, beril, q) => app());


来源:https://stackoverflow.com/questions/35163145/how-to-load-q-library-with-require-js

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