Уничтожение $ scope вручную - PullRequest
0 голосов
/ 27 июня 2018

ТЛ; др

Приложение загружает модули, обновляется каждые X минут, не уничтожает экземпляры модулей при перезагрузке. $scope.$on('$destroy') не вызывается. Модули DDoS API и замедление работы приложения. Вручную $broadcast от контроллера приложения, чтобы вызвать уничтожение (код ниже). Как вручную выгрузить экземпляр контроллера, когда $scope.$destroy() выдает ошибку «current is null»?

Более подробное объяснение

В настоящее время я работаю над приложением в стиле приборной панели, которое использует модули angularjs в качестве виджетов. Они загружаются динамически с использованием ocLazyLoad для сокращения времени загрузки приложения. Весь контент поставляется из JSON API.

Приборная панель перезагружает свой виджет каждые 30 минут (обновите код ниже), также перестраивая представление. Когда это происходит, существующие виджеты не разрушаются и остаются в памяти. Это означает, что каждые X минут, которые они устанавливают для обновления, также продолжает происходить. Таким образом, позволяя приложению работать в течение 2 часов, есть 4 экземпляра виджетов, запрашивающих данные каждые X секунд. Когда панель инструментов перезагружает свои виджеты, для старых экземпляров не вызывается событие уничтожения, поскольку они никогда не уничтожаются.

Я частично исправил это, заставив контроллер приборной панели передавать событие уничтожения, чтобы работающие контроллеры очищали свои $timeout с, однако это, очевидно, не удаляет загруженные экземпляры виджетов из памяти. Попытка вызвать $scope.$destroy() приводит к ошибке current is null, и с использованием приведенного ниже кода удаления элемента.

Вопрос в том, как еще можно уничтожить эти контроллеры?

кодовые блоки

Уничтожить приемник вещания

$scope.$on("destroy", function () {
    console.log("RMA Widget scope received destroy event. Destroying RMA widget");
    $scope.$destroy();
});

Удалить элементы модуля (виджета)

document.querySelectorAll(".widget").forEach((el) => {
    el.remove()
});

Загрузка модулей (виджетов). $scope.widgets используется в ng-repeat в теле.

$scope.widgets         = [];
for (let i = 0; i < rqData.data.data.widgets.length; i++) {
    const widget = rqData.data.data.widgets[i];
    $ocLazyLoad.load('app/' + widget.type + '/module.js');
    $scope.widgets.push({
        directive   : widget.type + '-widget',
        module      : 'app/' + widget.type + '/module.js',
        view        : 'app/' + widget.type + '/view.html',
        data        : Object.assign(widget.widget_id,
            {item_id : widget.id, content : widget.content}),
    });
}
$scope.timeout.compile = $timeout($ctrl.compileView, 3000);

1 Ответ

0 голосов
/ 27 июня 2018

Если вы используете ng-repeat, этого должно быть достаточно, чтобы удалить переменную $scope.widgets и установить ее заново. И я имею в виду действительно удалить переменную с delete $scope.widgets Может быть так:

function set_widgets(){
    if($scope.widgets !== undefined){
        delete $scope.widgets;
    }
    $scope.widgets         = [];
    for (let i = 0; i < rqData.data.data.widgets.length; i++) {
        const widget = rqData.data.data.widgets[i];
        $ocLazyLoad.load('app/' + widget.type + '/module.js');
        $scope.widgets.push({
                                directive   : widget.type + '-widget',
                                module      : 'app/' + widget.type + '/module.js',
                                view        : 'app/' + widget.type + '/view.html',
                                data        : Object.assign(widget.widget_id,
                                                            {item_id : widget.id, content : widget.content}),
                            });
    }
}

Edit: Все $ интервалы и $ тайм-ауты внутри контроллера виджетов должны быть остановлены вами самими, что не является чем-то связанным с областью действия контроллера

...