AngularJS: Правильний спосіб прив’язки до властивостей послуги


162

Я шукаю найкращу практику, як прив’язатись до сервісної властивості в AngularJS.

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

Нижче я маю два приклади того, як зв’язати властивості служби; вони обоє працюють. Перший приклад використовує базові прив'язки, а другий приклад використовує $ range. $ Watch для прив’язки до властивостей служби

Чи є один із цих прикладів кращим під час прив’язки до властивостей у службі чи є інший варіант, який мені не відомо про це, який би рекомендувався?

Передумовою цих прикладів є те, що сервіс повинен оновлювати свої властивості "lastUp updated" та "call" кожні 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>

Інший спосіб, коли я вирішив прив'язку до властивостей сервісу, - це використовувати $ range. $ 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>

Я знаю, що я можу використовувати $ rootcope. $ Мовлення в сервісі і $ root. $ On в контролері, але в інших прикладах, які я створив, що використовують $ Broadcast / $ в першій трансляції, не захоплюється контролер, але додаткові дзвінки, які транслюються, спрацьовують у контролері. Якщо вам відомо про спосіб вирішити проблему $ rootcope. $ Broadcast, будь ласка, надайте відповідь.

Але для перегляду того, що я згадував раніше, я хотів би знати найкращу практику прив’язки до властивостей служби.


Оновлення

На це питання було спочатку задано і відповіли у квітні 2013 року. У травні 2014 року Гіл Бірман дав нову відповідь, яку я змінив як правильну відповідь. Оскільки у відповіді Гіл Бірман дуже мало голосів, я занепокоєний тим, що люди, які читають це питання, не зважать на його відповідь на користь інших відповідей набагато більше голосів. Перш ніж приймати рішення про те, яка найкраща відповідь, я настійно рекомендую відповідь Гіл Бірман.


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

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

Проблема, про яку ви питаєте, стосується
натовної

Відповіді:


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's. Швидше, їх слід посипати $scope = injectable.data's, promise.then(..)' і і $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 повинні бути максимально простими і тонкими. Додаючи $ годинник у контролер, це ускладнює логіку. Просто посилаючись на значення в сервісі, це набагато простіше і, здається, більше способу AngularJS. -
Майк Барлоу - BarDev

3
"Десять заповідей" AngularJS. Це декларативно з причини.
pilau

Відповідь Джоша Девіда Міллера - не "НЕПРАВНИЙ". На все є час і місце.
JoshuaDavid

Я думаю, ти маєш рацію, @FireCoding. Я планую оновити відповідь.
Гіл Бірман

@GilBirman чудова відповідь. Ви б не заперечили написання та приклад директиви? Щоб проілюструвати те, що ви сказали, "єдине місце, яке дійсно має сенс від'єднати погляд від моделі, - це директива. [...] Швидше, у директиві потрібно вимагати API даних у формі об'єкта та надавати перевагу, використовуючи лише $ спостерігачі, створені ng-bind. "
klode

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}}
Марк Rajcok

2
@BarDev, для використання Timer.dataв $ watch, Timerмає бути визначено в області застосування $, оскільки вираження рядка, яке ви передаєте в $ watch, оцінюється відповідно до області застосування. Ось планкер, який показує, як зробити цю роботу. Параметр objectEquality задокументований тут - третій параметр - але насправді не дуже добре пояснений.
Марк Райкок

2
Продуктивність мудра, $watchдосить неефективна. Дивіться відповіді на stackoverflow.com/a/17558885/932632 та stackoverflow.com/questions/12576798/…
Крим

11
@Kyrm Це, мабуть, правда в деяких обставинах, але, маючи справу з продуктивністю, нам потрібно шукати "клінічно значущі" підвищення ефективності, а не лише статистично значущі, узагальнені. Якщо в існуючій програмі є проблема продуктивності, то її слід вирішити. В іншому випадку це лише випадок передчасної оптимізації, що призводить до важкого для читання, схильного до помилок коду, який не відповідає кращим практикам і який не продемонстрував користі.
Джош Девід Міллер

1
Якщо припустити, що спостерігач використовує функцію для виклику геттера, то так. Це добре працює. Я також прихильник служб, що повертають екземпляри в колекції, де замість цього досить непогано виконувати функції getter та setter es5.
Джош Девід Міллер

19

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

JavaScript має механізм передачі об'єктів за посиланням, тоді як він передає лише дрібну копію для значень "числа, рядки тощо".

У наведеному вище прикладі, замість прив’язки атрибутів служби, чому б ми не виставити послугу в область застосування?

$scope.hello = HelloService;

Цей простий підхід дозволить зробити двосторонній зв'язок і всі магічні речі, які вам потрібні. Не зламайте контролер за допомогою спостерігачів або непотрібної розмітки.

А якщо ви турбуєтесь про те, щоб ваш погляд випадково переписав атрибути служби, використовуйте 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};, просто приєднавши його до моделі, а не безпосередньо на Область застосування.
Скотт Сілві

1
AFAIK, посилання на об'єкт js працює на все, що знаходиться в Сервісі. Кодування таким чином: $ range.controllerVar = ServiceVar, все, що ви робите в $ range.controllerVar, також робиться в ServiceVar.
Кай Ван

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

12

Я думаю, що це питання має контекстуальну складову.

Якщо ви просто перетягуєте дані з сервісу та випромінюєте цю інформацію до його перегляду, я думаю, прив’язка безпосередньо до властивості послуги просто чудова. Я не хочу писати багато кодового шаблону, щоб просто зіставити сервісні властивості на властивості моделі, які потрібно споживати на мій погляд.

Крім того, продуктивність у кутовій основі ґрунтується на двох речах. Перший - скільки прив’язок є на сторінці. Друге - наскільки дорогі функції геттера. Місько про це говорить тут

Якщо вам потрібно виконати специфічну логіку для даних служби (на відміну від масажу даних, застосованих у самій службі), і результат цього впливає на модель даних, що піддаються перегляду, то я б сказав, що спостерігач $ доцільний, оскільки доки функція не є надзвичайно дорогою. У випадку з дорогою функцією, я б запропонував кешувати результати в локальній змінній (для контролера), виконуючи ваші складні операції поза функцією $ watcher, а потім прив'язуючи свій обсяг до результату цього.

Як застереження, ви не повинні вивішувати будь-які властивості безпосередньо за межами вашої долара. $scopeЗмінна не ваша модель. У ньому є посилання на вашу модель.

На мій погляд, "найкраща практика" для простого випромінювання інформації від служби вниз до перегляду:

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

І тоді ваш погляд міститиме {{model.timerData.lastupdated}}.


обережно з цією пропозицією, хтось, хто не знає JavaScript, може спробувати це зробити із властивістю, що є рядком. У такому випадку javascript не посилається на об’єкт, але в необробленому вигляді копіює рядок. (і це погано, тому що він не оновлюється, якщо зміниться)
Valerio

7
Чи я не пояснював це своїм "застереженням" про те, що ви завжди повинні використовувати крапку (мається на увазі не вивішувати її з $ range, а з $ range.model). Якщо у вас є $ range.model.someStringProperty, і ви посилаєтесь на model.someStringProperty, на ваш погляд, воно буде оновлено, оскільки внутрішні спостерігачі будуть на об’єкті, а не на опорі.
Скотт Сілві

6

Спираючись на наведені вище приклади, я думав, що я б перекинувся способом прозорого прив'язки змінної контролера до службової змінної.

У наведеному нижче прикладі зміни $scope.countзмінної Controller автоматично відображатимуться в countзмінній Service .

У виробництві ми фактично використовуємо цю прив'язку для оновлення ідентифікатора служби, яка потім асинхронно отримує дані та оновлює свої служби служби. Подальше прив'язка означає, що контролери автоматично оновлюються, коли служба оновлюється.

Код нижче можна побачити на веб-сайті 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);
    };

}

Це дивовижне рішення, дякую, це мені дуже допомогло, дуже розумний спосіб зробити це :)
Джавіс Перес

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

Зв'язувати будь-які дані, які надсилають службу - це не дуже гарна ідея (архітектура), але якщо вона вам більше потрібна, я пропоную вам два способи зробити це

1) ви можете отримати дані не всередині вашої служби. Ви можете отримати дані всередині вашого контролера / директиви, і у вас не виникне проблем пов’язати їх де завгодно

2) Ви можете використовувати події angularjs. Коли ви хочете, ви можете надіслати сигнал (від $ rootScope) і зловити його куди завгодно. Ви навіть можете надіслати дані про це ім'я події.

Можливо, це може вам допомогти. Якщо вам потрібно більше з прикладами, ось посилання

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



-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-Dricted 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);
    }
};

Потім я поставив слухача в свій контролер на потрібний канал і просто таким чином оновлюю локальну область.

На закінчення відзначимо , що це не так багато «Краща практика» - скоріше, його в основному перевагу - до тих пір , поки ви тримати речі SOLID і використовуючи слабкий зв'язок. Причиною я вважаю, що останній код полягає в тому, що EDA мають найнижчу можливу зв'язану природу. І якщо ви не надто стурбовані цим фактом, давайте уникати спільної роботи над одним і тим же проектом.

Сподіваюся, це допомагає ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.