Область действия Angular factory $ становится неограниченной

#javascript #angularjs

#javascript #angularjs

Вопрос:

У меня есть фабрика, которая возвращает объект, который я хочу отобразить во внешнем интерфейсе. Существует какое-то странное поведение (по крайней мере, для меня), когда я устанавливаю переменную следующим образом:

Я установил переменную ‘returnObject’ в начале контроллера, а затем позже назначаю ее в функции, которую выводит factory:

 module.factory("MyFactory", function ($http, $timeout, $cookies) {

    var returnObject = {};

    var myFunction = function(response) {

        // un-coomment this and it doesn't work
        // var test = {1: 'test 2'};
        // returnObject = test;

        // this works
        returnObject[1] = 'test';
       
    }

    var poller = function() {
        $http.get('data.json').then(function(response) {
            $timeout(poller, 5000);
            myFunction(response);
        });
        return returnObject;    
    };   

    return {
        unreadMessagePoller: poller,
    };

});
 
 app.controller('MainCtrl', MainCtrl);
function MainCtrl($scope, PollingService) {
    // poll for unread messages
    $scope.test = PollingService.unreadMessagePoller();
};
  
 

Если я вывожу переменную $scope в своем шаблоне, я вижу объект, как и ожидалось. Однако, если я не буду комментировать следующие строки:

 var test = {1: 'test 2'};
returnObject = test; 
 

Кажется, что область действия не привязана, а внешний вывод пуст. Я просто не понимаю!

Я создал плунжер, чтобы продемонстрировать проблему.

https://plnkr.co/edit/feVaotKCE9w2uQLJ

Обновить:

Вот еще один плунжер, другой подход к тому же поведению, мне кажется, это ошибка:

https://plnkr.co/edit/hEtPNWkkl5ZudEuB

Ответ №1:

 $scope.test = PollingService.unreadMessagePoller();
 

Возвращает исходный объект var returnObject = {};

Код:

 $http.get('data.json').then(function(response) {
     returnObject[1] = 'test';        
});
 

Изменяет содержимое исходного объекта.

С другой стороны, код:

 $http.get('data.json').then(function(response) {
    var test = {1: 'test 2'};
    returnObject = test;
});
 

Заменяет ссылку на объект на заводе новой ссылкой на объект.

Поскольку контроллер имеет исходную ссылку на объект, он не видит измененную ссылку на объект.

Именно так работает JavaScript.

Честно говоря, я избегаю метода возврата пустого объекта и последующего заполнения содержимого, когда данные поступают с сервера. Этот метод был популярен на заре AngularJS, но теперь новые API возвращают обещания, а не пустые объекты, которые мутируют.

Комментарии:

1. Выглядит ли это лучше с promise: plnkr.co/edit/Sm8eDHtpDaIShFf1 — На самом деле я уже пытался добавить обещание, но я добавил его в функцию, которая вызывается основной функцией, которую предоставляет служба!

2. Обещания ES6 не интегрированы с фреймворком AngularJS и его циклом дайджеста. AngularJS изменяет обычный поток JavaScript, предоставляя свой собственный цикл обработки событий. Это разбивает JavaScript на контекст выполнения классического и AngularJS. Только операции, которые применяются в контексте выполнения AngularJS, выиграют от привязки данных AngularJS, обработки исключений, просмотра свойств и т. Д.

3. Я все еще не знаю, как перезаписать объект, не используя его как ссылку — возможно, angular.copy()? На каждой итерации содержимое объекта может меняться, я подумал, что вместо поиска различий и их удаления самым быстрым и простым подходом было бы выполнить одно назначение для удаления предыдущих данных объекта?

4. $resource Служба использует angular.copy для заполнения содержимого объекта $resource, когда данные поступают с сервера. Объект $resource также имеет свойство с именем $promise , которое содержит обещание, возвращаемое службой $http.