AngularJS:如何观察服务变量?

ber*_*rto 409 watch angularjs angular-services

我有服务,说:

factory('aService', ['$rootScope', '$resource', function ($rootScope, $resource) {
  var service = {
    foo: []
  };

  return service;
}]);
Run Code Online (Sandbox Code Playgroud)

我想foo用来控制用HTML呈现的列表:

<div ng-controller="FooCtrl">
  <div ng-repeat="item in foo">{{ item }}</div>
</div>
Run Code Online (Sandbox Code Playgroud)

为了让控制器检测何时aService.foo更新,我将这个模式拼凑在一起,我将aService添加到控制器$scope,然后使用$scope.$watch():

function FooCtrl($scope, aService) {                                                                                                                              
  $scope.aService = aService;
  $scope.foo = aService.foo;

  $scope.$watch('aService.foo', function (newVal, oldVal, scope) {
    if(newVal) { 
      scope.foo = newVal;
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

这感觉很长,我一直在每个使用服务变量的控制器中重复它.有没有更好的方法来完成观察共享变量?

dth*_*dor 276

如果你想避免暴政和开销,你总是可以使用好的旧观察者模式$watch.

在服务中:

factory('aService', function() {
  var observerCallbacks = [];

  //register an observer
  this.registerObserverCallback = function(callback){
    observerCallbacks.push(callback);
  };

  //call this when you know 'foo' has been changed
  var notifyObservers = function(){
    angular.forEach(observerCallbacks, function(callback){
      callback();
    });
  };

  //example of when you may want to notify observers
  this.foo = someNgResource.query().$then(function(){
    notifyObservers();
  });
});
Run Code Online (Sandbox Code Playgroud)

在控制器中:

function FooCtrl($scope, aService){
  var updateFoo = function(){
    $scope.foo = aService.foo;
  };

  aService.registerObserverCallback(updateFoo);
  //service now in control of updating foo
};
Run Code Online (Sandbox Code Playgroud)

  • 我们使用像Angular这样的框架的原因是为了不制作我们自己的观察者模式. (106认同)
  • @Moo监听作用域上的`$ destory`事件,并向`aService`添加一个取消注册方法 (21认同)
  • 这个解决方案的优点是什么?它需要服务中的更多代码,并且在控制器中需要相同数量的代码(因为我们还需要在$ destroy上取消注册).我可以说是执行速度,但在大多数情况下它并不重要. (13认同)
  • `$ watch` vs.观察者模式只是选择是轮询还是推送,而且基本上是性能问题,所以在性能很重要时使用它.我使用观察者模式,否则我将不得不"深入"观察复杂的对象.我将整个服务附加到$ scope而不是查看单个服务值.我避免像魔鬼那样使用棱角分明的观察,在指令和原生角度数据绑定中发生了足够多的事情. (11认同)
  • 不知道这是一个比$ watch更好的解决方案,提问者要求一种简单的方式来共享数据,它看起来更加麻烦.我宁愿使用$ broadcast而不是这个 (6认同)
  • 即使性能不是一个问题,我也建议使用此解决方案,因为行为在代码中明确定义,并且不依赖于库魔术.好答案! (3认同)
  • 您需要有一个非常好的用例来证明在Angular中重新实现事件的合理性. (3认同)
  • 我觉得这太令人惊讶了 - 如果我看起来很粗糙,我会道歉 - 但这是一个简单的`getSet`方法.使用`Object.defineProperties(object,...)`或者如果你正在寻找`pubSub`方法,你也可以使用`$ rootScope.$ on('changed:someData',setSomeData)`& `$ rootScope.$ broadcast('changed:someData',someData)`.IMAINARY POINTS OFF这个答案:( (2认同)

Mat*_*ggi 227

在这样的场景中,多个/未知对象可能对更改感兴趣,请使用$rootScope.$broadcast正在更改的项目.

您应该能够$broadcast从相关服务中创建自己的侦听器注册表(必须在各种$ destroys上清理),而不是创建自己的侦听器注册表.

您仍然必须$on在每个侦听器中对处理程序进行编码,但该模式与多次调用分离$digest,因此避免了长时间运行的观察者的风险.

这样,听众也可以来自DOM和/或不同的子范围,而服务不会改变其行为.

**更新:示例**

广播在"全球"服务中最有意义,可能会影响您应用中的无数其他内容.一个很好的例子是用户服务,其中可能发生许多事件,例如登录,注销,更新,空闲等.我相信这是广播最有意义的地方,因为任何范围都可以监听事件,没有甚至注入服务,它不需要评估任何表达式或缓存结果来检查更改.它只是激发和忘记(所以确保它是一个发射后的通知,而不是需要采取行动的事情)

.factory('UserService', [ '$rootScope', function($rootScope) {
   var service = <whatever you do for the object>

   service.save = function(data) {
     .. validate data and update model ..
     // notify listeners and provide the data that changed [optional]
     $rootScope.$broadcast('user:updated',data);
   }

   // alternatively, create a callback function and $broadcast from there if making an ajax call

   return service;
}]);
Run Code Online (Sandbox Code Playgroud)

当save()函数完成且数据有效时,上面的服务会向每个范围广播一条消息.或者,如果它是$ resource或ajax提交,请将广播调用移动到回调中,以便在服务器响应时触发.广播非常适合这种模式,因为每个听众只需要等待事件而无需检查每个$ digest上的范围.听众看起来像:

.controller('UserCtrl', [ 'UserService', '$scope', function(UserService, $scope) {

  var user = UserService.getUser();

  // if you don't want to expose the actual object in your scope you could expose just the values, or derive a value for your purposes
   $scope.name = user.firstname + ' ' +user.lastname;

   $scope.$on('user:updated', function(event,data) {
     // you could inspect the data to see if what you care about changed, or just update your own scope
     $scope.name = user.firstname + ' ' + user.lastname;
   });

   // different event names let you group your code and logic by what happened
   $scope.$on('user:logout', function(event,data) {
     .. do something differently entirely ..
   });

 }]);
Run Code Online (Sandbox Code Playgroud)

其中一个好处是消除了多个手表.如果您正在组合字段或派生上述示例中的值,则必须同时查看firstname和lastname属性.只有在更新时替换了用户对象时,才能看到getUser()函数,如果用户对象仅更新了其属性,则不会触发它.在这种情况下,你必须做一个深刻的手表,这是更密集的.

$ broadcast将消息从它调用的范围发送到任何子范围.因此,从$ rootScope调用它将触发每个范围.例如,如果您从控制器的范围进行$广播,则只会在从控制器范围继承的范围内触发.$ emit方向相反,行为类似于DOM事件,因为它会使范围链冒泡.

请记住,在某些情况下,$ broadcast非常有意义,并且有些情况下$ watch是更好的选择 - 特别是在具有非常特定的监视表达的隔离范围中.

  • 只有当您的消费控制器具有多个可能的数据源时,这才是正确的设计模式; 换句话说,如果您有MIMO情况(多输入/多输出).如果您只是使用一对多模式,那么您应该使用直接对象引用并让Angular框架为您执行双向绑定.Horkyze将下面的内容联系起来,这是对自动双向绑定的一个很好的解释,它的局限性是:http://stsc3000.github.io/blog/2013/10/26/a-tale-of-frankenstein-and-结合对服务值功能于角点JS / (9认同)

Kry*_*rym 45

我使用与@dtheodot类似的方法,但使用角度承诺而不是传递回调

app.service('myService', function($q) {
    var self = this,
        defer = $q.defer();

    this.foo = 0;

    this.observeFoo = function() {
        return defer.promise;
    }

    this.setFoo = function(foo) {
        self.foo = foo;
        defer.notify(self.foo);
    }
})
Run Code Online (Sandbox Code Playgroud)

然后只需使用myService.setFoo(foo)方法更新foo服务.在您的控制器中,您可以将其用作:

myService.observeFoo().then(null, null, function(foo){
    $scope.foo = foo;
})
Run Code Online (Sandbox Code Playgroud)

前两个参数then是成功和错误回调,第三个是通知回调.

$ q的参考.

  • 用这种方法你会如何清理自己?当范围被销毁时,是否可以从promise中删除已注册的回调? (4认同)
  • 我有一个问题,在服务变量上做$ $ scope.$ watch`似乎不起作用(我正在观察的范围是从$ $ rootScope`继承的模式) - 这很有用.很酷的技巧,谢谢分享! (2认同)

Zym*_*tik 39

没有手表或观察者回调(http://jsfiddle.net/zymotik/853wvv7s/):

JavaScript的:

angular.module("Demo", [])
    .factory("DemoService", function($timeout) {

        function DemoService() {
            var self = this;
            self.name = "Demo Service";

            self.count = 0;

            self.counter = function(){
                self.count++;
                $timeout(self.counter, 1000);
            }

            self.addOneHundred = function(){
                self.count+=100;
            }

            self.counter();
        }

        return new DemoService();

    })
    .controller("DemoController", function($scope, DemoService) {

        $scope.service = DemoService;

        $scope.minusOneHundred = function() {
            DemoService.count -= 100;
        }

    });
Run Code Online (Sandbox Code Playgroud)

HTML

<div ng-app="Demo" ng-controller="DemoController">
    <div>
        <h4>{{service.name}}</h4>
        <p>Count: {{service.count}}</p>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

这个JavaScript的工作原理是我们从服务传递一个对象而不是一个值.从服务返回JavaScript对象时,Angular会将监视添加到其所有属性中.

还要注意我使用'var self = this',因为我需要在$ timeout执行时保持对原始对象的引用,否则'this'将引用window对象.

  • 这是一个很好的方法!有没有办法将服务的属性绑定到范围而不是整个服务?只是`$ scope.count = service.count`不起作用. (3认同)
  • 愿上帝保佑你。我想说我已经浪费了好几百万个小时。因为我正在努力应对 1.5 和 angularjs 从 1 到 2 的转变,并且还想共享数据 (2认同)

gan*_*raj 28

据我所知,你不必做那样详细的事情.您已经将foo从服务分配给范围,因为foo是一个数组(反过来它是一个通过引用分配的对象!).所以,你需要做的就是这样:

function FooCtrl($scope, aService) {                                                                                                                              
  $scope.foo = aService.foo;

 }
Run Code Online (Sandbox Code Playgroud)

如果有的话,同一个Ctrl中的其他变量依赖于foo更改然后是,你需要一个手表来观察foo并对该变量进行更改.但只要它是一个简单的参考,观看是不必要的.希望这可以帮助.

  • 我试过了,我无法使用`$ watch`来处理原语.相反,我在服务上定义了一个返回原始值的方法:`somePrimitive()= function(){return somePrimitive}`我为该方法分配了一个$ scope属性:`$ scope.somePrimitive = aService.somePrimitive; `.然后我在HTML中使用了scope方法:`<span> {{somePrimitive()}} </ span>` (35认同)
  • @MarkRajcok不要使用原语.将它们添加到对象中.基元不是可变的,因此双向数据绑定将不起作用 (4认同)
  • 这对我也不起作用.简单地指定`$ scope.foo = aService.foo`不会自动更新范围变量. (4认同)
  • @JimmyKane,是的,原语不应该用于双向数据绑定,但我认为问题是关于观察服务变量,而不是设置双向绑定.如果您只需要查看服务属性/变量,则不需要对象 - 可以使用基元. (3认同)
  • 在此设置中,我可以从范围更改aService值.但是范围不会随着aService的变化而变化. (3认同)
  • 正确你不能从Service变量中分配一个范围变量然后$ watch('foo',...我正在使用angular 1.3进行测试,当服务变量发生变化时,手表不会被触发 (2认同)

Nan*_*ard 28

我偶然发现了这个寻找类似问题的问题,但我认为它应该对正在发生的事情以及一些其他解决方案进行彻底的解释.

当您使用的角度表达式(如HTML中存在)时,Angular会自动设置$watchfor $scope.foo,并在$scope.foo更改时更新HTML .

<div ng-controller="FooCtrl">
  <div ng-repeat="item in foo">{{ item }}</div>
</div>
Run Code Online (Sandbox Code Playgroud)

这里未说明的问题是两件事之一正在影响aService.foo ,以至于没有发现变化.这两种可能性是:

  1. aService.foo 每次都被设置为一个新数组,导致它的引用过时.
  2. aService.foo正在更新,以便$digest在更新时不触发循环.

问题1:过时的参考文献

考虑到第一种可能性,假设$digest正在应用,如果aService.foo始终是相同的数组,则自动设置$watch将检测到更改,如下面的代码片段所示.

解决方案1-a:确保每次更新时数组或对象都是同一个对象

angular.module('myApp', [])
  .factory('aService', [
    '$interval',
    function($interval) {
      var service = {
        foo: []
      };

      // Create a new array on each update, appending the previous items and 
      // adding one new item each time
      $interval(function() {
        if (service.foo.length < 10) {
          var newArray = []
          Array.prototype.push.apply(newArray, service.foo);
          newArray.push(Math.random());
          service.foo = newArray;
        }
      }, 1000);

      return service;
    }
  ])
  .factory('aService2', [
    '$interval',
    function($interval) {
      var service = {
        foo: []
      };

      // Keep the same array, just add new items on each update
      $interval(function() {
        if (service.foo.length < 10) {
          service.foo.push(Math.random());
        }
      }, 1000);

      return service;
    }
  ])
  .controller('FooCtrl', [
    '$scope',
    'aService',
    'aService2',
    function FooCtrl($scope, aService, aService2) {
      $scope.foo = aService.foo;
      $scope.foo2 = aService2.foo;
    }
  ]);
Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html>

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body ng-app="myApp">
  <div ng-controller="FooCtrl">
    <h1>Array changes on each update</h1>
    <div ng-repeat="item in foo">{{ item }}</div>
    <h1>Array is the same on each udpate</h1>
    <div ng-repeat="item in foo2">{{ item }}</div>
  </div>
</body>

</html>
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样,所谓附加的ng-repeat aService.fooaService.foo更改时不会更新,但附加的ng-repeat aService2.foo 会更新.这是因为我们的引用aService.foo已经过时,但我们的引用aService2.foo并非如此.我们创建了对初始数组的引用$scope.foo = aService.foo;,然后服务在其下一次更新时将其丢弃,这意味着$scope.foo不再引用我们想要的数组.

但是,虽然有几种方法可以确保初始引用保持一致,但有时可能需要更改对象或数组.或者,如果服务属性引用像String或或Number?在这些情况下,我们不能简单地依赖于参考.那么,什么可以做什么?

之前给出的几个答案已经为这个问题提供了一些解决方案.但是,我个人赞成使用Jinthetallweeks在评论中提出的简单方法:

只需在html标记中引用aService.foo

解决方案1-b:将服务附加到作用域,并{service}.{property}在HTML中引用.

意思是,这样做:

HTML:

<div ng-controller="FooCtrl">
  <div ng-repeat="item in aService.foo">{{ item }}</div>
</div>
Run Code Online (Sandbox Code Playgroud)

JS:

function FooCtrl($scope, aService) {
    $scope.aService = aService;
}
Run Code Online (Sandbox Code Playgroud)

angular.module('myApp', [])
  .factory('aService', [
    '$interval',
    function($interval) {
      var service = {
        foo: []
      };

      // Create a new array on each update, appending the previous items and 
      // adding one new item each time
      $interval(function() {
        if (service.foo.length < 10) {
          var newArray = []
          Array.prototype.push.apply(newArray, service.foo);
          newArray.push(Math.random());
          service.foo = newArray;
        }
      }, 1000);

      return service;
    }
  ])
  .controller('FooCtrl', [
    '$scope',
    'aService',
    function FooCtrl($scope, aService) {
      $scope.aService = aService;
    }
  ]);
Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html>

<head>
  <script data-require="angular.js@1.4.7" data-semver="1.4.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body ng-app="myApp">
  <div ng-controller="FooCtrl">
    <h1>Array changes on each update</h1>
    <div ng-repeat="item in aService.foo">{{ item }}</div>
  </div>
</body>

</html>
Run Code Online (Sandbox Code Playgroud)

这样,$watch将解析aService.foo每个$digest,这将获得正确更新的值.

这是你试图用你的解决方法做的一种,但是方式要少得多.我们加了一个不必要的$watch,其中明确提出控制器foo$scope,每当它改变.你并不需要额外的$watch,当你连接aService,而不是aService.foo$scope,并明确绑定到aService.foo该标记.


现在,假设$digest正在应用一个循环,这一切都很好.在上面的示例中,我使用Angular的$interval服务来更新数组,这些数组会$digest在每次更新后自动启动一个循环.但是,如果服务变量(无论出于何种原因)未在"Angular world"中更新,该怎么办?换句话说,我们有一个$digest能够自动启动周期会在服务性质的变化?


问题2:失踪 $digest

这里的许多解决方案都将解决这个问题,但我同意Code Whisperer:

我们使用像Angular这样的框架的原因是为了不制作我们自己的观察者模式

因此,我更愿意继续使用aService.fooHTML标记中的引用,如上面第二个示例所示,而不必在Controller中注册其他回调.

解决方案2:使用setter和getter $rootScope.$apply()

我很惊讶没有人建议使用二传手吸气剂.这种能力是在ECMAScript5中引入的,因此已经存在多年了.当然,这意味着,无论出于何种原因,如果你需要支持真正的旧浏览器,那么这种方法将不起作用,但我觉得getter和setter在JavaScript中被大量使用.在这种特殊情况下,它们可能非常有用:

factory('aService', [
  '$rootScope',
  function($rootScope) {
    var realFoo = [];

    var service = {
      set foo(a) {
        realFoo = a;
        $rootScope.$apply();
      },
      get foo() {
        return realFoo;
      }
    };
  // ...
}
Run Code Online (Sandbox Code Playgroud)

angular.module('myApp', [])
  .factory('aService', [
    '$rootScope',
    function($rootScope) {
      var realFoo = [];

      var service = {
        set foo(a) {
          realFoo = a;
          $rootScope.$apply();
        },
        get foo() {
          return realFoo;
        }
      };

      // Create a new array on each update, appending the previous items and 
      // adding one new item each time
      setInterval(function() {
        if (service.foo.length < 10) {
          var newArray = [];
          Array.prototype.push.apply(newArray, service.foo);
          newArray.push(Math.random());
          service.foo = newArray;
        }
      }, 1000);

      return service;
    }
  ])
  .controller('FooCtrl', [
    '$scope',
    'aService',
    function FooCtrl($scope, aService) {
      $scope.aService = aService;
    }
  ]);
Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html>

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body ng-app="myApp">
  <div ng-controller="FooCtrl">
    <h1>Using a Getter/Setter</h1>
    <div ng-repeat="item in aService.foo">{{ item }}</div>
  </div>
</body>

</html>
Run Code Online (Sandbox Code Playgroud)

这里我在服务函数中添加了一个'private'变量:realFoo.使用对象上的get foo()set foo()函数分别更新和检索此get service.

注意$rootScope.$apply()在set函数中的使用.这可确保Angular知道对其的任何更改service.foo.如果你得到'inprog'错误,请看这个有用的参考页面,或者如果你使用Angular> = 1.3,你可以使用$rootScope.$applyAsync().

如果aService.foo要经常更新,也要小心这一点,因为这可能会对性能产生重大影响.如果性能是一个问题,您可以使用setter设置类似于其他答案的观察者模式.

  • 这是正确,最简单的解决方案.正如@NanoWizard所说,$ digest监视`services`而不是属于服务本身的属性. (3认同)

Rod*_*ira 8

您可以在$ rootScope中插入服务并观察:

myApp.run(function($rootScope, aService){
    $rootScope.aService = aService;
    $rootScope.$watch('aService', function(){
        alert('Watch');
    }, true);
});
Run Code Online (Sandbox Code Playgroud)

在你的控制器中:

myApp.controller('main', function($scope){
    $scope.aService.foo = 'change';
});
Run Code Online (Sandbox Code Playgroud)

其他选项是使用外部库,如:https://github.com/melanke/Watch.JS

适用于:IE 9 +,FF 4 +,SF 5 +,WebKit,CH 7 +,OP 12 +,BESEN,Node.JS,Rhino 1.7+

您可以观察一个,多个或所有对象属性的更改.

例:

var ex3 = {
    attr1: 0,
    attr2: "initial value of attr2",
    attr3: ["a", 3, null]
};   
watch(ex3, function(){
    alert("some attribute of ex3 changes!");
});
ex3.attr3.push("new value");?
Run Code Online (Sandbox Code Playgroud)

  • 我不相信这个答案不是最顶级的!这是最优雅的解决方案(IMO),因为它减少了信息熵并可能减少了对其他中介处理程序的需求.如果可以,我会更多地投票. (2认同)

Fla*_*ken 6

您可以在工厂内观察更改,然后广播更改

angular.module('MyApp').factory('aFactory', function ($rootScope) {
    // Define your factory content
    var result = {
        'key': value
    };

    // add a listener on a key        
    $rootScope.$watch(function () {
        return result.key;
    }, function (newValue, oldValue, scope) {
        // This is called after the key "key" has changed, a good idea is to broadcast a message that key has changed
        $rootScope.$broadcast('aFactory:keyChanged', newValue);
    }, true);

    return result;
});
Run Code Online (Sandbox Code Playgroud)

然后在你的控制器中:

angular.module('MyApp').controller('aController', ['$rootScope', function ($rootScope) {

    $rootScope.$on('aFactory:keyChanged', function currentCityChanged(event, value) {
        // do something
    });
}]);
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以将所有相关的工厂代码放在其描述中,然后您只能依赖外部的广播


hay*_*lem 6

== ==修订

非常简单现在$ watch.

笔在这里.

HTML:

<div class="container" data-ng-app="app">

  <div class="well" data-ng-controller="FooCtrl">
    <p><strong>FooController</strong></p>
    <div class="row">
      <div class="col-sm-6">
        <p><a href="" ng-click="setItems([ { name: 'I am single item' } ])">Send one item</a></p>
        <p><a href="" ng-click="setItems([ { name: 'Item 1 of 2' }, { name: 'Item 2 of 2' } ])">Send two items</a></p>
        <p><a href="" ng-click="setItems([ { name: 'Item 1 of 3' }, { name: 'Item 2 of 3' }, { name: 'Item 3 of 3' } ])">Send three items</a></p>
      </div>
      <div class="col-sm-6">
        <p><a href="" ng-click="setName('Sheldon')">Send name: Sheldon</a></p>
        <p><a href="" ng-click="setName('Leonard')">Send name: Leonard</a></p>
        <p><a href="" ng-click="setName('Penny')">Send name: Penny</a></p>
      </div>
    </div>
  </div>

  <div class="well" data-ng-controller="BarCtrl">
    <p><strong>BarController</strong></p>
    <p ng-if="name">Name is: {{ name }}</p>
    <div ng-repeat="item in items">{{ item.name }}</div>
  </div>

</div>
Run Code Online (Sandbox Code Playgroud)

JavaScript的:

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

app.factory('PostmanService', function() {
  var Postman = {};
  Postman.set = function(key, val) {
    Postman[key] = val;
  };
  Postman.get = function(key) {
    return Postman[key];
  };
  Postman.watch = function($scope, key, onChange) {
    return $scope.$watch(
      // This function returns the value being watched. It is called for each turn of the $digest loop
      function() {
        return Postman.get(key);
      },
      // This is the change listener, called when the value returned from the above function changes
      function(newValue, oldValue) {
        if (newValue !== oldValue) {
          // Only update if the value changed
          $scope[key] = newValue;
          // Run onChange if it is function
          if (angular.isFunction(onChange)) {
            onChange(newValue, oldValue);
          }
        }
      }
    );
  };
  return Postman;
});

app.controller('FooCtrl', ['$scope', 'PostmanService', function($scope, PostmanService) {
  $scope.setItems = function(items) {
    PostmanService.set('items', items);
  };
  $scope.setName = function(name) {
    PostmanService.set('name', name);
  };
}]);

app.controller('BarCtrl', ['$scope', 'PostmanService', function($scope, PostmanService) {
  $scope.items = [];
  $scope.name = '';
  PostmanService.watch($scope, 'items');
  PostmanService.watch($scope, 'name', function(newVal, oldVal) {
    alert('Hi, ' + newVal + '!');
  });
}]);
Run Code Online (Sandbox Code Playgroud)