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()”,它将正常工作。

但我想在 'require' 函数之外使用那个 'myCpane' 变量(出于多种原因)。我知道由于 Dojo 的组件加载过程而延迟了“require()”回调函数的执行。

我的问题是,

  1. 如何阻止“require()”函数,直到它完成执行它的回调函数。

因此,当控件从“require()”函数中出来时,变量“myCpane”不会是“未定义的”

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

为了克服这个问题,我编写了一个小函数来加载模块并等待模块加载完成

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循环,控件永远不会进入'require()的回调函数来设置变量“moduleObject”的值。

'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/

我还建议您考虑以下两种策略之一来实现相同目标:

  1. 给出ContentPaneanid并通过 dijit 获取其引用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 转换为您的 myCpane,它在函数内声明为变量 (var $$),加载程序完成时回调的函数需要 modules

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 回答