3

Dojo 1.7.2 で AMD ローダーを使用して、以下のような Dojo ウィジェットを作成しました。

var myCpane;

require([
            "dijit/layout/ContentPane"
        ], function(ContentPane) {
        myCpane = new ContentPane();
});

myCpane.startup();  // It gives 'myCpane' as undefined

上記の例では、最後のステートメントで変数「myCpane」が「未定義」になっています。「require()」コールバック関数内で「myCpane.startup()」を使用すると、正常に動作します。

しかし、私はその「myCpane」変数を「require」関数の外側で使用したいと考えています(多くの理由から)。Dojo によるコンポーネントのロード プロセスが原因で、'require()' コールバック関数の実行が遅れていることはわかっています。

私の質問は、

  1. コールバック関数の実行が完了するまで「require()」関数をブロックする方法。

したがって、変数「myCpane」は、コントロールが「require()」関数から出たときに「未定義」にはなりません。

================================================== =========

この問題を克服するために、モジュールをロードし、モジュールのロードが完了するまで待機する小さな関数を作成しました。

LoadModule: function(modulePath) { // modulePath = "dijit/layout/ContentPane" 
        var moduleObject = undefined; 

        require({async:  false}, [modulePath], function(getModuleObject) { 
                moduleObject = getModuleObject; 
        }); 

        // Wait until the module loads completes 
        while(moduleObject === undefined); 

        // Return the loaded module. 
        return moduleObject; 
} 

関数の出力は常に while ループを実行しており、変数「moduleObject」に値を設定するために、コントロールが「require()」のコールバック関数内に入ることはありません。

「require()」関数がコールバック関数を呼び出すのはいつですか? ブラウザー デバッガー ウィンドウを使用して、ファイル 'ContentPane.js' が正しく読み込まれていることを確認しましたが、コールバック関数が呼び出されません。while ループをコメントすると、コールバックが正しく呼び出されます。

私の場合、コントロールがコールバック関数の中に入るのはいつですか?

4

2 に答える 2

3

何を達成しようとしているのかはわかりませんが、プログラミングのアンチパターンのように見えます。とにかく、次の方法でこれを達成できますdojo/_base/Deferred

require(["dojo/_base/Deferred"], function(Deferred) {

    var deferred = new Deferred();

    require(["dijit/layout/ContentPane"], function(ContentPane) {
        var myCpane = new ContentPane();
        deferred.resolve(myCpane); //resolve, i.e. call `then` callback
    });

    deferred.then(function(myCpane) {
        console.log(myCpane);
        myCpane.startup();
    });

});​    

jsFiddle でそれをいじってください: http://jsfiddle.net/phusick/HYQEd/

また、同じことを達成するために、次の 2 つの戦略のいずれかを検討することをお勧めします。

  1. ContentPaneanを指定し、 dijitidの を介して参照を取得しますregistry.byId()
  2. 別のモジュールでインスタンスを作成ContentPaneし、そのモジュールの戻り値として公開します。

    // file: myCpane.js
    define(["dijit/layout/ContentPane"], function(ContentPane) { 
        var myCpane = new ContentPane();
        return myCpane;
    });
    
    
    // file: main.js
    require(["./myCpane"], function(myCpane) {
        myCpane.startup();
    });
    
于 2012-05-17T09:05:45.917 に答える
1

これは、AMDローダーの質問よりも範囲の問題につながると思います。検討

var x;
function foo() {
  x = { bar : 1 };
}

// you wouldn't expect to have reference to x variable here
if(typeof x.bar == "undefined") console.log(x);
// foo() is called at a random time - or in dojo loader case, when modules are present
foo();
console.log(x.bar); // oohh now its there ^^

この場合の x は、関数内で変数 (var $$) として宣言されている myCpane に変換されます

Deferred は、以下で説明するように、これに適したハンドラーです。ただし、すでに切り離された (非同期) 関数フローにいる場合は、わずかなオーバーヘッドが発生します。完全に制御するには、require()を調べてください。これも同様に実行できます。

var myCpane;

require({ async:  false  }, [
            "dijit/layout/ContentPane"
        ], function(ContentPane) {
        myCpane = new ContentPane();
});
// require does not return until module loading is done and callback executed
myCpane.startup();  
于 2012-05-17T09:58:52.250 に答える