2012-07-16 10 views
6

Ich versuche, Backbone-Anwendung mit dem Marionette-Plugin zusammenzusetzen, und habe einige Schwierigkeiten, Initialisierungen zu bekommen, um so zu arbeiten, wie ich es erwartet hatte. Ich habe den folgenden Code:Wie man Async-Code in einem Backbone-Marionette-Initialisierer behandelt

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

Hinweis im Code oben, dass ich zwei console.log Anrufe, ein in dem Initialisierer, und einen in den initialize:after Handler. Beide protokollieren die gleiche Objekteigenschaft. Wie Sie sehen können, was ich erfahre, ist, dass der console.log Aufruf in der initialize:after Handler vor der in der success Handler des Initialisierers aufgerufen wird. Ich weiß, dass dies daran liegt, dass der Initialisierer einen asynchronen Aufruf enthält ... was ich wissen muss ist, wie ich sicherstellen kann, dass der gesamte asynchrone Code in meinen Initialisierer (n) vollständig ist, bevor ich irgendetwas anderes in der Anwendung mache ? Gibt es dafür ein gutes Muster? Ich habe nichts in den Dokumenten gefunden, das anzeigt, wie man damit richtig umgeht.

Danke.

Antwort

7

Wie kann ich sicherstellen, dass der gesamte Async-Code in meinen Initialisierer (n) vollständig ist, bevor Sie etwas anderes in der Anwendung ausführen?

Verwenden Sie nicht das Ereignis initialize:after. Aktivieren Sie stattdessen Ihr eigenes Ereignis vom success-Aufruf, und binden Sie dann den Startcode Ihrer App an diesen.

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

diese Weise können Sie ein Ereignis nach dem Asynchron Sachen auslösen beendet ist, wird der Code in der Prozedur bedeutet, bis nicht ausgeführt, nachdem die anfängliche Asynchron-Aufruf zurückgegeben hat und die Dinge sind eingerichtet.

+0

Nun, da ich diese Antwort schriftlich gesehen habe, scheint es für mich offensichtlich zu sein, dass ich ein bisschen dumm bin, dass ich es selbst nicht herausfinden konnte. Danke Derick. –

+2

nichts dummes darüber. es ist nicht offensichtlich, wenn Sie die Antwort nicht wissen :) –

+0

Ich dachte dies, und fühlte mich dumm, es zu googeln. aber die Syntax, die du gepostet hast, half mir, meine Gedanken zu klären;) Danke Derick für die Antwort und danke OP für die Frage! – jkat98

0

Ich schrieb eine Überschreibung der Startmethode mit jQuery deffereds, so dass Sie einen Async-Initialisierer wie Authentifizierung angeben können. Die Startmethode wartet dann, bis alle Zurückgestelltes aufgelöst sind, und beendet dann den Start.

Ich ersetze Marionette Callbacks mit meiner neuen Sync-Callback-Klasse, so dass ich die normalen Methodenaufrufe in der App verwenden kann. Schauen Sie sich meine Lösung an und schauen Sie, ob das überhaupt hilft. https://github.com/AlexmReynolds/Marionette.Callbacks

0

Dies kann verwendet werden, um Aufgaben zu erledigen, bevor der Rest Ihrer Anwendung beginnt. Überprüfen Sie die 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); 
Verwandte Themen