How to handle asynchronous code in a basic puppet initializer

I am trying to build a basic application using a puppet plugin, and I am having problems initializing to work the way I expected. I have the following code:

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

Note that in the above code, I have two calls to console.log , one in the initializer and one in the initialize:after handler. Both register the same property of the object. As you can see, what I'm experiencing is that the console.log call in the initialize:after handler is called before it is executed in the success handler of the initializer. I understand that this is because the initializer has an asynchronous call in it ... I need to know how I can make sure all the async code in my initializer is complete before doing anything else in the application? Is there a good sample for this? I did not find anything in the docs indicating how to handle this correctly.

Thanks.

+6
source share
3 answers

how can I make sure that all async code in my initializer is complete before doing anything else in the application?

Do not use the initialize:after event. Instead, fire your own event from the success call, and then bind the application launch code from it.

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

This way you fire the event after the asynchronous code completes, that is, the code in the handler will not be executed until the original asynchronous call is returned and everything is configured.

+7
source

I wrote an override of the start method using jQuery deffereds so that you can specify an Async initializer, such as authentication. Then, the start method waits until all pending decisions have been resolved, and then finishes the start.

I am replacing puppet callbacks with my new sync callback class, so I can use regular method calls in the application. Take a look at my solution and see if this helps at all. https://github.com/AlexmReynolds/Marionette.Callbacks

0
source

This can be used to complete tasks before starting the rest of your application. Check the 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); 
0
source

Source: https://habr.com/ru/post/920610/


All Articles