2012-07-16 29 views
6

我正在嘗試使用牽線木偶插件將骨幹應用程序放在一起,並且遇到了一些問題,使得初始化程序以我期望的方式工作。我有以下代碼:如何處理骨幹牽線木偶初始化程序中的異步代碼

var MyApp = new Backbone.Marionette.Application(); 

MyApp.addRegions({ 
    region1 : '#div1', 
    region2 : '#div2' 
}); 

MyApp.Resources = { }; 

MyApp.bind('initialize:before', function (options) { 
    // display a modal dialog for app initialization 
    options.initMessageId = noty({ 
     text : 'Initializing MyApp (this should only take a second or two)', 
     layout : 'center', 
     speed : 1, 
     timeout : false, 
     modal : true, 
     closeOnSelfClick : false 
    }); 
}); 

MyApp.addInitializer(function (options) { 
    $.ajax({ 
     url: options.apiUrl + '/my-app-api-module', 
     type: 'GET', 
     contentType: 'application/json; charset=utf-8', 
     success: function (results) { 
      MyApp.Resources.urls = results; 
      console.log(MyApp.Resources.urls); // <- THIS returns an object 
     } 
    }); 
}); 

MyApp.bind('initialize:after', function (options) { 
    // initialization is done...close the modal dialog 
    if (options.initMessageId) { 
     $.noty.close(options.initMessageId); 
    } 

    if (Backbone.history) { 
     Backbone.history.start(); 
    } 

    console.log(MyApp.Resources.urls); // <- THIS returns 'undefined' BEFORE the console.log in the initializer above 
}); 

注意在上面的代碼中,我有兩個console.log電話,一個在初始化,以及一個在initialize:after處理。兩者都記錄相同的對象屬性。正如你所看到的,我正在經歷的是initialize:after handler中的console.log調用在之前被調用在初始化器的success處理程序中。我意識到這是因爲初始化程序中有一個異步調用...我需要知道的是,如何在應用程序中執行其他任何操作之前,確保初始化程序中的所有異步代碼都已完成?這是否有一個好的模式?我沒有在文檔中找到任何指示如何正確處理這個問題。

謝謝。

回答

7

如何確保在執行應用程序中的其他任何操作之前,我的初始化程序中的所有異步代碼都已完成?

請勿使用initialize:after事件。相反,從success調用觸發您自己的事件,然後綁定您的應用程序啓動該代碼。

MyApp.addInitializer(function (options) { 
    $.ajax({ 
     url: options.apiUrl + '/my-app-api-module', 
     type: 'GET', 
     contentType: 'application/json; charset=utf-8', 
     success: function (results) { 
      MyApp.Resources.urls = results; 

      // trigger custom event here 
      MyApp.vent.trigger("some:event:to:say:it:is:done") 

     } 
    }); 
}); 

// bind to your event here, instead of initialize:after 
MyApp.vent.bind('some:event:to:say:it:is:done', function (options) { 

    // initialization is done...close the modal dialog 
    if (options.initMessageId) { 
     $.noty.close(options.initMessageId); 
    } 

    if (Backbone.history) { 
     Backbone.history.start(); 
    } 

    console.log(MyApp.Resources.urls); 
}); 

這樣,你是你的異步東西后觸發事件已經結束,這意味着在處理程序的代碼將無法運行,直到最初的異步調用返回,事情成立後。

+0

現在看到這個答案的書面形式,對我來說似乎很明顯,我覺得有點愚蠢,我無法自己弄清楚。謝謝Derick。 – 2012-07-16 17:17:58

+2

沒有什麼愚蠢的。這是不明顯的,如果你不知道答案:) – 2012-07-16 21:25:04

+0

我在想這個,並愚蠢的谷歌搜索它。但是你發佈的語法有助於澄清我的想法;)感謝Derick回覆並感謝OP提出問題! – jkat98 2013-07-23 15:36:28

0

我寫了一個覆蓋啓動方法使用jQuery的緩存,所以你可以指定一個異步初始化,如身份驗證。 start方法等待直到所有延遲被解析,然後結束開始。

我用我的新同步回調類替換了木偶的回調,所以我可以使用應用程序中的常規方法調用。看看我的解決方案,看看是否有幫助。 https://github.com/AlexmReynolds/Marionette.Callbacks

0

這可用於在應用程序的其餘部分開始之前完成任務。 檢查documentation

// Create our Application 
var app = new Mn.Application(); 

// Start history when our application is ready 
app.on('start', function() { 
    Backbone.history.start(); 
}); 

// Load some initial data, and then start our application 
loadInitialData().then(app.start);