2012-05-17 78 views
3

我創建道場插件像下面在1.7.2道場道場1.7如何使用道場部件以外的要求()

var myCpane; 

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

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

使用AMD裝載機在上述例子中,在最後statment,變量'如果我在'require()'回調函數中使用'myCpane.startup()',那麼myCpane會以'未定義'的形式出現,那麼它會正常工作。

但我想在'require'函數外部使用'myCpane'變量(原因很多)。由於Dojo的組件加載過程,我知道'require()'回調函數的執行延遲了。

我的問題是,

  1. 如何阻止「需要()函數,直到它完成執行它的回調函數。

所以變量「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循環,那麼回調被正確調用。

當我的情況下,控件將進入回調函數的內部?

+1

JavaScript是單線程的,當一個異步事件發生時,它就會進入_Event Queue_。瀏覽器有一個內部循環,叫做_Event Loop_,它檢查隊列和處理事件,執行函數等等[[source](http://javascript.info/tutorial/events-and-timing-depth#asynchronous-events))。因此加載'ContentPane.js',但在LoadModule函數結束之前,加載程序的回調將不會執行,這要歸功於'while' _busy loop_永遠不會發生。 您應該改變[思考](http://goo.gl/jJZzb)的方式,因爲您無法改變JavaScript的工作方式。 – phusick

+0

這件事讓我感到困惑,因爲對我來說,這只是一種不同的思考方式。我接觸到的事實是我需要了解更多關於Javascript的知識。我現在正在思考的是,我需要創建自己的控制器對象(這是一個可以接收對Dojo環境的必要引用的函數),然後我可以用範圍內的所有引用來執行我的代碼。 – mydoghasworms

回答

3

我不知道什麼是你即將實現,但它看起來對我來說就像a programming anti-pattern。在的jsfiddle

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

});​  

惹它:反正你可以通過dojo/_base/Deferred實現這一http://jsfiddle.net/phusick/HYQEd/

我也建議你考慮這兩種策略之一,以實現相同的:

  1. 給的ContentPaneid並通過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(); 
    }); 
    
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 $$)函數裏面,那就是當加載完成requireing模塊爲回調函數。

Deferred是一個很好的處理程序,如下所述。儘管如此,如果你已經在分離(異步)函數流程中,那麼可能會有一點點開銷。對於完全控制,考慮需要()你可以這樣做,以及:

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

{async:false}不能正常工作,執行控制只是來自require函數。 – sokid