ASP.NET MVC 3 одностраничное приложение, использующее Javascript / jQuery AJAX: проблемы с памятью и отдельным DOM - PullRequest
4 голосов
/ 14 марта 2012

Недавно я создал одностраничный ASP.NET MVC 3 с пользовательским интерфейсом JS / jQuery (поверх HTML-представления), общая идея работы с Javascript приведена ниже.Я сталкиваюсь с проблемами, когда GC неправильно освобождает память и оставляет большое количество элементов (24 000 для самой большой формы, 15–20 КБ и 1 КБ в зависимости от того, какая форма загружается / выгружается) в отдельном DOM (для просмотра в инструментах разработчика Chrome Heap Profiler)).

 var MainApp = function () {
    var meBase = this;
    this.activeObject = undefined;

    this.someFunc = function (val1, val2, etc) {
        //Some operation here
    }
    this.GetView(x, y, z)
    {
        if (meBase.activeObject != null) {
            meBase.BustActive(x, y, z);
        } else {
            if (condition) {
                //Load static html via $.get
            } else {
                switch (activeObjectSelector) {
                    case CASEHERE:
                        self.activeObject = new SomeObject();
                        self.activeObject.BeginInit();
                        break;
                    case .....
                }
            }
        }
    }
    this.BustActive = function (x, y, z) {
        if (meBase.activeObject.Destroy()) {
            meBase.activeObject = null;
            meBase.GetView(x, y, z);
        }
    }
}
var SomeObject = function () {
    var meBase = this;
    this.Bindings = [];
    this.Container = "#somecontainer";
    //Some Properties

    this.Unbind = function () {
        $("#Somecontainer .bound").each(function () {
            if ($(this)["click"] && $.isFunction($(this)["click"])) {
                $(this).unbind('click');
            }
            if ($(this)["blur"] && $.isFunction($(this)["blur"])) {
                $(this).unbind('blur');
            } if ($(this)["change"] && $.isFunction($(this)["change"])) {
                $(this).unbind('change');
            }
            if ($(this)["mouseenter"] && $.isFunction($(this)["mouseenter"])) {
                $(this).unbind('mouseenter');
            } if ($(this)["mouseleave"] && $.isFunction($(this)["mouseleave"])) {
                $(this).unbind('mouseleave');
            }
        });

        //iterate through meBase.Bindings to remove any 'special' bindings such as 'live/die'
    }
    this.MapEvents = function () {
        //For Example

        $("#Somecontainer #element").click(meBase.SomeAction).addClass('bound');

        // create object with removal function for 'special' bindings such as 'live/die'
        // and push it into meBase.Bindings;
    }
    this.InitUI = function () {
        //Setup tabs, datepickers, etc
    }
    this.Destroy = function () {
        meBase.Unbind();

        //remove object fields and methods
        delete meBase.someProp;

        $(meBase.Container).empty();
        delete meBase.BeginInit;
        delete meBase.InitUI;
        delete meBase.MapEvents;
        delete meBase.SomeAction;
        delete meBase;
        return true;
    }
    this.SomeAction = function () {
        //Do something productive..hopefully
    }
    this.ProcessView = function (data) {
        $("#MainContainer").fadeOut(150, "swing", function () {
            $(this).empty().append(data);
        });
    }
    this.LoadView = function () {
        $.ajax({
            url: '/somewhere/something',
            type: 'GET',
            success: meBase.ProccessView, error: SomeGlobalObject.LogAjaxError
        });
    }
    this.BeginInit = function () {
        //Load pages via ajax
        meBase.LoadView();
        meBase.InitUI();
        meBase.MapEvents();
        return true;
    }

}

Я попытался выполнить итерации с помощью javascript для удаления событий и элементов в функции .Destroy (), и это существенно уменьшило количество элементов, оставшихся в Detached DOM, по сравнению с $ (container) .empty () или $ (контейнер) .remove ().Но моя память никогда не восстанавливается должным образом, она постоянно увеличивается во время каждой загрузки / выгрузки.Есть случайные падения, но не та сумма, которую я ожидал.Нормально ли так много элементов оставаться зависшими, или есть какая-то фундаментальная проблема с тем, как работает мой код?

Спасибо, что нашли время, чтобы прочитать это!

Первое сообщение, пожалуйста, будьте осторожны ...

1 Ответ

1 голос
/ 15 марта 2012

Я также недавно создавал некоторые одностраничные приложения в .Net MVC3. Я подозреваю, что ваши проблемы возникают из-за того, что Microsoft, пытаясь не допустить разработчиков на JS и C #, очень плохо работает с Javascript и Jquery на вашей странице.

Лучший совет, который я могу вам дать, заключается в том, что вам нужно избавиться от всей бессмысленности Microsoft и создать часть html / js вашего приложения, как если бы она была полностью независимой от платформы. Это означает, что вы в основном будете использовать M в MVC, и вам понадобится только достаточное количество C для управления вашим Ms. Если View - это все HTML и Javascript, жизнь действительно становится намного проще. Вот как начать:

  • Удалить все предварительно упакованные серверные коды, включая страницы Razor или ASPX.
  • Переключиться на статические файлы HTML, статические файлы JS
  • (Необязательно) Используйте Require.js для управления зависимостями JS (внимательно прочитайте документы, сначала это кажется странным, но невероятно мощным)
  • (Необязательно) Используйте Spine.js , чтобы придать вашему коду JS некоторую структуру
  • (Необязательно) Используйте Handlebars.js для вашего механизма шаблонов на стороне клиента

Require и Spine быстро стали моими любимыми инструментами для создания одностраничных приложений. Они предоставляют вам очень мощные и гибкие инструменты, которые помогут вам управлять увеличенным объемом кода Javascript, который вы будете писать в любом одностраничном приложении.

Как только ваш клиентский код будет полностью отключен от попыток Microsoft разрушить Javascript, вы сможете сосредоточиться на своих данных, которые должны использовать службы отдыха на основе JSON в MVC3. Вы можете получить помощь по этим здесь и здесь .

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...