Как обрабатывать асинхронный код в инициализаторе марионетки магистрали

Я пытаюсь собрать базовое приложение с помощью плагина марионетки, и у меня возникли проблемы с тем, чтобы инициализаторы работали так, как я ожидал. У меня есть следующий код:

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. Оба регистрируют одно и то же свойство объекта. Как видите, я столкнулся с тем, что вызов console.log в обработчике initialize:after вызывается до вызова в обработчике success инициализатора. Я понимаю, что это связано с тем, что в инициализаторе есть асинхронный вызов... мне нужно знать, как я могу убедиться, что весь асинхронный код в моих инициализаторах завершен, прежде чем делать что-либо еще в приложении. ? Есть ли хороший шаблон для этого? Я не нашел в документах ничего, указывающего, как правильно с этим справиться.

Спасибо.


person Bob Yexley    schedule 16.07.2012    source источник


Ответы (3)


как я могу убедиться, что весь асинхронный код в моих инициализаторах завершен, прежде чем делать что-либо еще в приложении?

Не используйте событие 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);
});

Таким образом, вы запускаете событие после того, как ваши асинхронные действия завершены, что означает, что код в обработчике не будет выполняться до тех пор, пока не вернется первоначальный асинхронный вызов и все не будет настроено.

person Derick Bailey    schedule 16.07.2012
comment
Что ж, теперь, увидев этот ответ в письменной форме, мне кажется очевидным, что я чувствую себя немного глупо из-за того, что не смог понять это сам. Спасибо, Дерик. - person Bob Yexley; 16.07.2012
comment
ничего глупого в этом нет. это не очевидно, если вы не знаете ответа :) - person Derick Bailey; 17.07.2012
comment
Я думал об этом и чувствовал себя глупо, когда гуглил. но опубликованный вами синтаксис помог прояснить мои мысли;) Спасибо Дерику за ответ и спасибо ОП за вопрос! - person jkat98; 23.07.2013

Я написал переопределение метода запуска, используя отложенные jQuery, чтобы вы могли указать асинхронный инициализатор, такой как аутентификация. Затем метод запуска ждет, пока не будут разрешены все отложенные, а затем завершает запуск.

Я заменяю обратные вызовы марионеток своим новым классом обратных вызовов синхронизации, чтобы я мог использовать обычные вызовы методов в приложении. Взгляните на мое решение и посмотрите, поможет ли оно вообще. https://github.com/AlexmReynolds/Marionette.Callbacks

person Alex Reynolds    schedule 06.01.2014

Это можно использовать для выполнения задач до того, как запустится остальная часть вашего приложения. Ознакомьтесь с документацией.

// 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);
person shau    schedule 03.07.2015