AngularJS: правильный способ привязки к свойствам сервиса


162

Я ищу лучший способ привязки к свойству службы в AngularJS.

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

Ниже у меня есть два примера того, как привязать свойства в сервисе; они оба работают. В первом примере используются базовые привязки, а во втором - $ scope. $ Watch для привязки к свойствам службы.

Любой из этих примеров предпочтителен при привязке к свойствам в службе или есть другой вариант, который я не знаю, который будет рекомендован?

Предпосылкой этих примеров является то, что сервис должен обновлять свои свойства «lastUpdated» и «звонки» каждые 5 секунд. После обновления свойств службы представление должно отражать эти изменения. Оба эти примера работают успешно; Интересно, есть ли лучший способ сделать это?

Базовая привязка

Следующий код можно просмотреть и запустить здесь: http://plnkr.co/edit/d3c16z

<html>
<body ng-app="ServiceNotification" >

    <div ng-controller="TimerCtrl1" style="border-style:dotted"> 
        TimerCtrl1 <br/>
        Last Updated: {{timerData.lastUpdated}}<br/>
        Last Updated: {{timerData.calls}}<br/>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
    <script type="text/javascript">
        var app = angular.module("ServiceNotification", []);

        function TimerCtrl1($scope, Timer) {
            $scope.timerData = Timer.data;
        };

        app.factory("Timer", function ($timeout) {
            var data = { lastUpdated: new Date(), calls: 0 };

            var updateTimer = function () {
                data.lastUpdated = new Date();
                data.calls += 1;
                console.log("updateTimer: " + data.lastUpdated);

                $timeout(updateTimer, 5000);
            };
            updateTimer();

            return {
                data: data
            };
        });
    </script>
</body>
</html>

Другой способ, которым я решил связать со свойствами сервиса, это использовать $ scope. $ Watch в контроллере.

$ Сфера. $ Часы

Следующий код можно просмотреть и запустить здесь: http://plnkr.co/edit/dSBlC9

<html>
<body ng-app="ServiceNotification">
    <div style="border-style:dotted" ng-controller="TimerCtrl1">
        TimerCtrl1<br/>
        Last Updated: {{lastUpdated}}<br/>
        Last Updated: {{calls}}<br/>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
    <script type="text/javascript">
        var app = angular.module("ServiceNotification", []);

        function TimerCtrl1($scope, Timer) {
            $scope.$watch(function () { return Timer.data.lastUpdated; },
                function (value) {
                    console.log("In $watch - lastUpdated:" + value);
                    $scope.lastUpdated = value;
                }
            );

            $scope.$watch(function () { return Timer.data.calls; },
                function (value) {
                    console.log("In $watch - calls:" + value);
                    $scope.calls = value;
                }
            );
        };

        app.factory("Timer", function ($timeout) {
            var data = { lastUpdated: new Date(), calls: 0 };

            var updateTimer = function () {
                data.lastUpdated = new Date();
                data.calls += 1;
                console.log("updateTimer: " + data.lastUpdated);

                $timeout(updateTimer, 5000);
            };
            updateTimer();

            return {
                data: data
            };
        });
    </script>
</body>
</html>

Я знаю, что могу использовать $ rootscope. $ Broadcast в сервисе и $ root. $ On в контроллере, но в других созданных мной примерах, которые используют $ broadcast / $ в первой трансляции, не фиксируется контроллер, но дополнительные вызовы, которые передаются, запускаются в контроллере. Если вам известен способ решения проблемы с $ rootcope. $ Broadcast, пожалуйста, предоставьте ответ.

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


Обновить

Этот вопрос был первоначально задан и получен ответ в апреле 2013 года. В мае 2014 года Джил Бирман предоставил новый ответ, который я изменил как правильный ответ. Поскольку у ответа Гила Бирмана очень мало голосов «за», я обеспокоен тем, что люди, читающие этот вопрос, проигнорируют его ответ в пользу других ответов с большим количеством голосов. Прежде чем принять решение о том, что является лучшим ответом, я настоятельно рекомендую ответ Гила Бирмана.


Я думаю, что ответ Джоша Дэвида Миллера лучше ответа Гила Бирмана. А использование $ watch, $ watchGroup и $ watchCollection может даже сделать его еще лучше. Разделение проблем очень важно для приложений среднего и большого размера.
Джонатан

@ bardev Я думаю, что оба ответа были бесполезны, и новые разработчики поняли бы их полностью неправильно.
Залабоза

Проблема, о которой вы спрашиваете, касается поведения переменных объектов в JavaScript, на которые я
ссылаюсь

Ответы:


100

Рассмотрим некоторые плюсы и минусы второго подхода :

  • 0 {{lastUpdated}} вместо того {{timerData.lastUpdated}}, что может быть так же легко {{timer.lastUpdated}}, как я могу поспорить, более читабельно (но давайте не будем спорить ... Я даю этой точке нейтральную оценку, чтобы вы сами решили)

  • +1 Может быть удобно, что контроллер действует как своего рода API для разметки, так что если каким-то образом структура модели данных изменится, вы можете (теоретически) обновить отображения API контроллера, не касаясь части html.

  • -1 Однако теория не всегда практика , и я обычно нахожу того , чтобы изменить разметку и логику контроллера , когда изменения называются для, так или иначе . Таким образом, дополнительные усилия по написанию API сводят на нет его преимущество.

  • -1 Кроме того, такой подход не очень СУХОЙ.

  • -1 Если вы хотите привязать данные к ng-modelсвоему коду, они становятся еще менее СУХИМЫМИ, так как вам нужно переупаковать их $scope.scalar_valuesв контроллере, чтобы сделать новый вызов REST.

  • -0.1 Есть крошечный хит производительности, создающий дополнительных наблюдателей. Кроме того, если к модели привязаны свойства данных, которые не нужно отслеживать в конкретном контроллере, это создаст дополнительные издержки для глубоких наблюдателей.

  • -1 Что если нескольким контроллерам нужны одинаковые модели данных? Это означает, что у вас есть несколько API для обновления при каждом изменении модели.

$scope.timerData = Timer.data;сейчас это звучит очень заманчиво ... Давайте немного углубимся в этот последний момент ... О каких изменениях в модели мы говорили? Модель на серверной части (сервер)? Или модель, которая создана и живет только в передней части? В любом случае то, что по существу является API отображения данных, относится к внешнему уровню обслуживания (угловая фабрика или служба). (Обратите внимание, что ваш первый пример - мои предпочтения - не имеет такого API на уровне сервисов , что хорошо, потому что он достаточно прост и не нуждается в нем.)

В заключение , все не должно быть отделено. А что касается полного отделения разметки от модели данных, недостатки перевешивают преимущества.


Контроллеры, как правило, не должны быть засорены с $scope = injectable.data.scalar. Скорее, они должны быть посыпаны $scope = injectable.data's, promise.then(..)' s, и $scope.complexClickAction = function() {..}'s

В качестве альтернативного подхода к разделению данных и, следовательно, к инкапсуляции представлений, единственное место, в котором действительно имеет смысл отделить представление от модели, - это директива . Но даже там не $watchскалярные значения в функциях controllerили link. Это не сэкономит время и не сделает код более понятным и удобочитаемым. Это даже не облегчит тестирование, поскольку надежные тесты в угловом режиме обычно проверяют полученный DOM в любом случае . Скорее, в директиве требуется ваш API данных в виде объекта, и вы предпочитаете использовать только те, которые $watchсозданы ng-bind.


Пример http://plnkr.co/edit/MVeU1GKRTN4bqA3h9Yio

<body ng-app="ServiceNotification">
    <div style="border-style:dotted" ng-controller="TimerCtrl1">
        TimerCtrl1<br/>
        Bad:<br/>
        Last Updated: {{lastUpdated}}<br/>
        Last Updated: {{calls}}<br/>
        Good:<br/>
        Last Updated: {{data.lastUpdated}}<br/>
        Last Updated: {{data.calls}}<br/>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
    <script type="text/javascript">
        var app = angular.module("ServiceNotification", []);

        function TimerCtrl1($scope, Timer) {
            $scope.data = Timer.data;
            $scope.lastUpdated = Timer.data.lastUpdated;
            $scope.calls = Timer.data.calls;
        };

        app.factory("Timer", function ($timeout) {
            var data = { lastUpdated: new Date(), calls: 0 };

            var updateTimer = function () {
                data.lastUpdated = new Date();
                data.calls += 1;
                console.log("updateTimer: " + data.lastUpdated);

                $timeout(updateTimer, 500);
            };
            updateTimer();

            return {
                data: data
            };
        });
    </script>
</body>

ОБНОВЛЕНИЕ : я наконец вернулся к этому вопросу, чтобы добавить, что я не думаю, что любой подход "неправильн". Первоначально я писал, что ответ Джоша Дэвида Миллера был неверным, но в ретроспективе его положения полностью верны, особенно его точка зрения о разделении интересов.

Помимо разделения проблем (но косвенно связанных), есть еще одна причина для защитного копирования, которую я не смог рассмотреть. Этот вопрос в основном касается чтения данных непосредственно из службы. Но что, если разработчик в вашей команде решит, что контроллеру необходимо каким-то тривиальным образом преобразовать данные, прежде чем представление отобразит их? (Должны ли контроллеры преобразовывать данные вообще - другое обсуждение.) Если она сначала не сделает копию объекта, она может невольно вызвать регрессию в другом компоненте представления, который потребляет те же данные.

Что на самом деле подчеркивает этот вопрос, так это архитектурные недостатки типичного углового приложения (и на самом деле любого приложения JavaScript): тесная взаимосвязь проблем и изменчивость объектов. Недавно я влюбился в архитектурное приложение с React и неизменяемыми структурами данных. Это прекрасно решает две следующие проблемы:

  1. Разделение проблем : компонент потребляет все свои данные через реквизиты и практически не зависит от глобальных синглетонов (таких как сервисы Angular) и ничего не знает о том, что произошло над ним в иерархии представлений.

  2. Изменчивость : все реквизиты являются неизменяемыми, что исключает риск невольной мутации данных.

Angular 2.0 в настоящее время находится на пути к тому, чтобы позаимствовать у React значительные средства для достижения двух указанных выше пунктов.


1
Чем больше я работаю с AngularJS, тем больше понимаю. Я считаю, что контроллеры AngularJS должны быть максимально простыми и тонкими. Добавление $ watches в контроллер усложняет логику. Просто ссылаясь на значение в сервисе, это намного проще и кажется, что это больше похоже на AngularJS. -
Майк Барлоу - BarDev

3
«Десять заповедей» AngularJS. Это декларативно по причине.
плов

Ответ Джоша Дэвида Миллера не «НЕПРАВИЛЬНЫЙ». Есть время и место для всего.
Джошуа Дэвид

Я думаю, что вы правы, @FireCoding. Я планирую обновить ответ.
Гил Бирман

@GilBirman отличный ответ. Не могли бы вы написать и пример для директивы? Чтобы проиллюстрировать то, что вы сказали, «единственное место, в котором действительно имеет смысл отделить представление от модели, - это директива. [...] Скорее, в директиве требуется ваш API данных в виде объекта, и вы предпочитаете использовать только $ наблюдатели, созданные ng-bind. "
Клод

78

С моей точки зрения, это $watchбыл бы лучший способ практики.

Вы можете немного упростить свой пример:

function TimerCtrl1($scope, Timer) {
  $scope.$watch( function () { return Timer.data; }, function (data) {
    $scope.lastUpdated = data.lastUpdated;
    $scope.calls = data.calls;
  }, true);
}

Это все, что вам нужно.

Поскольку свойства обновляются одновременно, вам нужно всего лишь один час. Кроме того, так как они происходят из одного, довольно маленького объекта, я изменил его, чтобы просто наблюдать за Timer.dataсвойством. Последний переданный параметр $watchуказывает ему проверять наличие глубокого равенства, а не просто проверять, является ли ссылка одинаковой.


Чтобы обеспечить немного контекста, я бы предпочел, чтобы этот метод помещал стоимость услуги непосредственно в область действия, чтобы обеспечить надлежащее разделение интересов. Ваше мнение не должно знать ничего о ваших услугах, чтобы работать. Задача контроллера - склеить все вместе; его задача состоит в том, чтобы получать данные из ваших служб и обрабатывать их любым необходимым способом, а затем предоставлять вашему представлению всю необходимую информацию. Но я не думаю, что его работа состоит в том, чтобы просто передать сервис прямо на вид. Иначе, что вообще делает контроллер? Разработчики AngularJS следовали той же причине, когда они решили не включать какую-либо «логику» в шаблоны (например, ifоператоры).

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


3
Можете ли вы уточнить немного? Вы предпочитаете часы $, потому что представление менее связано с сервисом? {{lastUpdated}}{{timerData.lastUpdated}}
То

2
@BarDev, который нужно использовать Timer.dataв $ watch, Timerдолжен быть определен в $ scope, потому что строковое выражение, которое вы передаете в $ watch, сравнивается с областью видимости. Вот плункер, который показывает, как заставить это работать. Параметр objectEquality здесь задокументирован - 3-й параметр - но не очень хорошо объяснен.
Марк Райкок

2
Производительность мудрая, $watchдовольно неэффективная. См. Ответы на stackoverflow.com/a/17558885/932632 и stackoverflow.com/questions/12576798/…
Крым,

11
@Kyrm Это, вероятно, верно в некоторых обстоятельствах, но когда речь идет о производительности, нам нужно искать «клинически значимые» улучшения производительности, а не только статистически значимые, обобщенные. Если в существующем приложении есть проблема с производительностью, ее следует устранить. В противном случае, это всего лишь случай преждевременной оптимизации, что приводит к тому, что код становится сложнее для чтения и подвержен ошибкам, который не соответствует передовым методам и не имеет очевидных преимуществ.
Джош Дэвид Миллер

1
Предполагая, что наблюдатель использует функцию для вызова получателя, тогда да. Это работает хорошо. Я также сторонник сервисов, возвращающих экземпляры в коллекцию, где функции get5 и setter у es5 довольно неплохи.
Джош Дэвид Миллер

19

Поздно до вечеринки, но для будущих Googlers - не используйте предоставленный ответ.

В JavaScript есть механизм передачи объектов по ссылке, в то время как он передает только поверхностную копию значений «числа, строки и т. Д.».

В приведенном выше примере, вместо того, чтобы связывать атрибуты сервиса, почему бы нам не выставить сервис в область?

$scope.hello = HelloService;

Этот простой подход сделает angular способным выполнять двустороннюю привязку и все магические вещи, которые вам нужны. Не взламывайте свой контроллер наблюдателями или ненужной разметкой.

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

Последний совет: если вы тратите свое время на работу с контроллером больше, чем на сервисы, то вы делаете это неправильно :(.

В указанном вами демонстрационном коде я бы порекомендовал вам сделать следующее:

 function TimerCtrl1($scope, Timer) {
   $scope.timer = Timer;
 }
///Inside view
{{ timer.time_updated }}
{{ timer.other_property }}
etc...

Редактировать:

Как я уже упоминал выше, вы можете контролировать поведение атрибутов службы, используя defineProperty

Пример:

// Lets expose a property named "propertyWithSetter" on our service
// and hook a setter function that automatically saves new value to db !
Object.defineProperty(self, 'propertyWithSetter', {
  get: function() { return self.data.variable; },
  set: function(newValue) { 
         self.data.variable = newValue; 
         // let's update the database too to reflect changes in data-model !
         self.updateDatabaseWithNewData(data);
       },
  enumerable: true,
  configurable: true
});

Теперь в нашем контроллере, если мы делаем

$scope.hello = HelloService;
$scope.hello.propertyWithSetter = 'NEW VALUE';

наш сервис изменит значение, propertyWithSetterа также опубликует новое значение в базе данных!

Или мы можем выбрать любой подход, который захотим.

Обратитесь к документации MDN для defineProperty.


Я уверен, что это то, что я описал выше, $scope.model = {timerData: Timer.data};просто прикрепив его к модели, а не прямо в Scope.
Скотт Сильви

1
AFAIK, ссылка на объект js работает для всего в Сервисе. Кодировка выглядит так: $ scope.controllerVar = ServiceVar, все, что вы делаете в $ scope.controllerVar, также выполняется в ServiceVar.
Кай Ван

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

12

Я думаю, что этот вопрос имеет контекстную составляющую.

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

Кроме того, производительность в угловых зависит от двух вещей. Во-первых, сколько привязок на странице. Во-вторых, насколько дорогими являются функции получения. Миско говорит об этом здесь

Если вам необходимо выполнить специфичную для экземпляра логику для данных службы (в отличие от массирования данных, применяемого внутри самой службы), и результат этого влияет на модель данных, предоставляемую представлению, тогда я бы сказал, что $ watcher подходит, так как Пока функция не очень дорогая. В случае с дорогой функцией я бы предложил кэшировать результаты в локальной (для контроллера) переменной, выполняя сложные операции вне функции $ watcher, а затем связывая вашу область видимости с результатом этого.

В качестве предостережения вы не должны вешать какие-либо свойства прямо за пределы вашей области видимости. $scopeПеременная не ваша модель. Он имеет ссылки на вашу модель.

На мой взгляд, «лучшая практика» для простого распространения информации от сервиса до просмотра:

function TimerCtrl1($scope, Timer) {
  $scope.model = {timerData: Timer.data};
};

И тогда ваш взгляд будет содержать {{model.timerData.lastupdated}}.


Осторожнее с этим предложением, кто-то не разбирающийся в javascript может попытаться сделать это со свойством, которое является строкой. В этом случае javascript не делает ссылку на объект, а копирует строку в формате raw. (и это плохо, потому что он не обновляется, если он меняется)
Валерио

7
Разве я не рассмотрел это с моим 'предостережением', что вы всегда должны использовать точку (то есть не вешайте ее за пределы $ scope, а за исключением $ scope.model). Если у вас есть $ scope.model.someStringProperty и вы ссылаетесь на model.someStringProperty в своем представлении, оно будет обновлено, потому что внутренние наблюдатели будут на объекте, а не на реквизите.
Скотт Сильви

6

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

В приведенном ниже примере изменения $scope.countпеременной Controller будут автоматически отражены в countпеременной Service .

На самом деле мы используем привязку this для обновления идентификатора службы, который затем асинхронно извлекает данные и обновляет свои служебные переменные. Дальнейшее связывание означает, что контроллеры автоматически обновляются при обновлении службы.

Код ниже можно увидеть на http://jsfiddle.net/xuUHS/163/

Посмотреть:

<div ng-controller="ServiceCtrl">
    <p> This is my countService variable : {{count}}</p>
    <input type="number" ng-model="count">
    <p> This is my updated after click variable : {{countS}}</p>

    <button ng-click="clickC()" >Controller ++ </button>
    <button ng-click="chkC()" >Check Controller Count</button>
    </br>

    <button ng-click="clickS()" >Service ++ </button>
    <button ng-click="chkS()" >Check Service Count</button>
</div>

Услуги / Контроллер:

var app = angular.module('myApp', []);

app.service('testService', function(){
    var count = 10;

    function incrementCount() {
      count++;
      return count;
    };

    function getCount() { return count; }

    return {
        get count() { return count },
        set count(val) {
            count = val;
        },
        getCount: getCount,
        incrementCount: incrementCount
    }

});

function ServiceCtrl($scope, testService)
{

    Object.defineProperty($scope, 'count', {
        get: function() { return testService.count; },
        set: function(val) { testService.count = val; },
    });

    $scope.clickC = function () {
       $scope.count++;
    };
    $scope.chkC = function () {
        alert($scope.count);
    };

    $scope.clickS = function () {
       ++testService.count;
    };
    $scope.chkS = function () {
        alert(testService.count);
    };

}

Это отличное решение, спасибо, это мне очень помогло, очень умный способ сделать это :)
Javis Perez

2

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

Вот почему:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.7/angular.min.js"></script>
<body ng-app="BindToService">

  <div ng-controller="BindToServiceCtrl as ctrl">
    ArrService.arrOne: <span ng-repeat="v in ArrService.arrOne">{{v}}</span>
    <br />
    ArrService.arrTwo: <span ng-repeat="v in ArrService.arrTwo">{{v}}</span>
    <br />
    <br />
    <!-- This is empty since $scope.arrOne never changes -->
    arrOne: <span ng-repeat="v in arrOne">{{v}}</span>
    <br />
    <!-- This is not empty since $scope.arrTwo === ArrService.arrTwo -->
    <!-- Both of them point the memory space modified by the `push` function below -->
    arrTwo: <span ng-repeat="v in arrTwo">{{v}}</span>
  </div>

  <script type="text/javascript">
    var app = angular.module("BindToService", []);

    app.controller("BindToServiceCtrl", function ($scope, ArrService) {
      $scope.ArrService = ArrService;
      $scope.arrOne = ArrService.arrOne;
      $scope.arrTwo = ArrService.arrTwo;
    });

    app.service("ArrService", function ($interval) {
      var that = this,
          i = 0;
      this.arrOne = [];
      that.arrTwo = [];

      $interval(function () {
        // This will change arrOne (the pointer).
        // However, $scope.arrOne is still same as the original arrOne.
        that.arrOne = that.arrOne.concat([i]);

        // This line changes the memory block pointed by arrTwo.
        // And arrTwo (the pointer) itself never changes.
        that.arrTwo.push(i);
        i += 1;
      }, 1000);

    });
  </script>
</body> 

Вы можете играть в это на этом поршне .


1

Я бы предпочел держать своих наблюдателей как можно меньше. Моя причина основана на моем опыте, и можно утверждать это теоретически.
Проблема с использованием наблюдателей заключается в том, что вы можете использовать любое свойство в области для вызова любого из методов в любом компоненте или услуге, которая вам нравится.
В реальном проекте очень скоро вы получите неразрешимую (точнее сказать, трудно прослеживаемую) цепочку вызываемых методов и изменяемых значений, что особенно делает трагический процесс адаптации.


0

Связывать любые данные, которые отправляет сервис, не очень хорошая идея (архитектура), но если вам это нужно больше, я предлагаю вам 2 способа сделать это

1) вы можете получить данные не в своей службе. Вы можете получить данные в вашем контроллере / директиве, и у вас не возникнет проблем с их привязкой куда-либо

2) вы можете использовать события angularjs. Когда бы вы ни захотели, вы можете отправить сигнал (из $ rootScope) и перехватить его где угодно. Вы даже можете отправить данные об этом eventName.

Может быть, это может помочь вам. Если вам нужно больше с примерами, вот ссылка

http://www.w3docs.com/snippets/angularjs/bind-value-between-service-and-controller-directive.html


-1

Что о

scope = _.extend(scope, ParentScope);

Где ParentScope является внедренным сервисом?


-2

Самые элегантные решения ...

app.service('svc', function(){ this.attr = []; return this; });
app.controller('ctrl', function($scope, svc){
    $scope.attr = svc.attr || [];
    $scope.$watch('attr', function(neo, old){ /* if necessary */ });
});
app.run(function($rootScope, svc){
    $rootScope.svc = svc;
    $rootScope.$watch('svc', function(neo, old){ /* change the world */ });
});

Кроме того, я пишу EDA (Event-Driven Architectures), поэтому я склонен делать что-то вроде следующего [упрощенная версия]:

var Service = function Service($rootScope) {
    var $scope = $rootScope.$new(this);
    $scope.that = [];
    $scope.$watch('that', thatObserver, true);
    function thatObserver(what) {
        $scope.$broadcast('that:changed', what);
    }
};

Затем я помещаю слушателя в свой контроллер на желаемом канале и просто обновляю свой локальный объем таким образом.

В заключение, есть не так много «Лучшей практики» - скорее, в основном это предпочтение - до тех пор, пока вы сохраняете вещи твердыми и используете слабую связь. Причина, по которой я бы выступил за последний код, заключается в том, что EDA имеют наименьшую возможную связь по своей природе. И если вы не слишком обеспокоены этим фактом, давайте избегать совместной работы над одним проектом.

Надеюсь это поможет...

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.