2012-07-16 60 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);