Dojo 1.7 how to use dojo components outside of req

2019-05-11 20:56发布

问题:

I have created Dojo widget like below using AMD loader in Dojo 1.7.2

var myCpane;

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

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

In the above example, in the last statment, the variable 'myCpane' is coming as 'undefined', if I use the 'myCpane.startup()' inside the 'require()' callback function then, it will work fine.

But I want to use that 'myCpane' variable on outside of the 'require' function (for many reasons). I know the 'require()' callback function execution delayed due to the component loading process by Dojo.

My question is,

  1. How to block the 'require()' function until it completes to execute it's callback function.

So the variable 'myCpane' will not be 'undefined' when the control come out from the 'require()' function

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

To overcome this issue, I have written a small function to load the modules and wait until the module load complete

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

The output of the function is always executing the while loop, the control never comes inside of 'require()'s callback function to set the value to the variable "moduleObject".

When the 'require()' function will call it's callback function? I have verified using the browser debugger window the file 'ContentPane.js' is loaded properly, but the callback function is not called, If I comment the while loop then, the callback is called properly.

When the control will come inside of the callback function in my case ?

回答1:

I'm not sure what are you about to achieve, but it looks for me like a programming anti-pattern. Anyway you can achieve this via 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();
    });

});​    

Mess with it at jsFiddle: http://jsfiddle.net/phusick/HYQEd/

I would also suggest you consider one of these two strategies to achieve the same:

  1. Give the ContentPane an id and obtain its reference via dijit's registry.byId().
  2. Create ContentPane instance in a separate module and expose it as a return value of that module:

    // file: myCpane.js
    define(["dijit/layout/ContentPane"], function(ContentPane) { 
        var myCpane = new ContentPane();
        return myCpane;
    });
    
    
    // file: main.js
    require(["./myCpane"], function(myCpane) {
        myCpane.startup();
    });
    


回答2:

I think this goes more to scope issue then amd loader question; consider

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 in this case translates to your myCpane, which is declared as variable (var $$) inside a function, the function that is callback for when loader is done requireing modules.

The Deferred is a nice handler for this as stated below. A slight overhead though, if youre allready in a detached (async) function flow. For full control, look into require() you could do this as well:

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


标签: dojo amd