web-dev-qa-db-ja.com

RequireJSで動的に「コンテキストのモジュール名がまだロードされていません」というエラーが発生しますか?

RequireJSの他のモジュールを「動的に」ロードするモジュールを定義する方法はありますか?はいの場合、オプティマイザー(r.js)はどのように/いつモジュールを含める必要があるかを理解しますか?

たとえば、dynModulesを名前/パスのペアを定義するモジュールとします。

define([], function () {
    return ['moduleA', 'moduleB']; // Array of module names
});

別のモジュールは、配列に基づいてモジュールを動的にロードします。これは動作しません

define(['dyn_modules'], function (dynModules) {
    for(name in dynModules) {   
        var module = require(path); // Call RequireJS require
    }

    // ...
});

...私に与えます:

不明なエラー:モジュール名「moduleA」はコンテキスト_に対してまだロードされていません。 require([]) http://requirejs.org/docs/errors.html#notloaded を使用します

エラーを解決することができますが、それはもう「動的」ではありません:

define(['dyn_modules', 'moduleA', 'moduleB'], function (dynModules) {
    for(name in dynModules) {   
        var module = require(path); // Call RequireJS require
    }

    // ...
});
56
gremo

制限は、単純化されたCommonJS構文と通常のコールバック構文に関連しています。

モジュールのロードは、ダウンロードのタイミングが不明なため、本質的に非同期プロセスです。ただし、サーバー側のCommonJS仕様のエミュレーションにおけるRequireJSは、単純化された構文を提供しようとします。このようなことをするとき:

var foomodule = require('foo');
// do something with fooModule

舞台裏で行われているのは、RequireJSが関数コードの本体を調べて、「foo」が必要であることを解析し、関数の実行前にそれをロードしていることです。ただし、変数など、単純な文字列以外のもの(例など).

var module = require(path); // Call RequireJS require

...次に、Requireはこれを解析して自動的に変換することができません。解決策は、コールバック構文に変換することです。

var moduleName = 'foo';
require([moduleName], function(fooModule){
    // do something with fooModule
})

上記を考えると、標準構文を使用するための2番目の例を書き直すことができます。

define(['dyn_modules'], function (dynModules) {
    require(dynModules, function(){
        // use arguments since you don't know how many modules you're getting in the callback
        for (var i = 0; i < arguments.length; i++){
            var mymodule = arguments[i];
            // do something with mymodule...
        }
    });

});

編集:あなた自身の答えから、アンダースコア/ロダッシュを使用していることがわかります。したがって、_.values_.objectを使用すると、上記のように引数配列のループを簡素化できます。

68
explunit

自分に答えます。 RequireJS Webサイトから:

//THIS WILL FAIL
define(['require'], function (require) {
    var namedModule = require('name');
});

Requirejsは、上記のファクトリー関数を呼び出す前にすべての依存関係をロードして実行する必要があるため、これは失敗します。 [...]したがって、依存関係配列を渡さないか、依存関係配列を使用している場合は、その中のすべての依存関係をリストします。

私の解決策:

// Modules configuration (modules that will be used as Jade helpers)
define(function () {
    return {
        'moment':   'path/to/moment',
        'filesize': 'path/to/filesize',
        '_':        'path/to/lodash',
        '_s':       'path/to/underscore.string'
    };
});

ローダー:

define(['jade', 'lodash', 'config'], function (Jade, _, Config) {
    var deps;

    // Dynamic require
    require(_.values(Config), function () {
        deps = _.object(_.keys(Config), arguments);

        // Use deps...
    });
});
7
gremo