mikeb mikeb - 5 months ago 7
AngularJS Question

Angular service and watching a variable

I have an angular service that gets an

$http
promise from a factory making a REST call, which works fine.:

var UserService = function($cookies, DataFactory, jsonHelper, $q) {
var USER_KEY = 'user';
var USERNAME_KEY = 'username';

var svcData = {
u: null,
b: null,
}

var service = {
setUser : function(user){
svcData.u = user;
$cookies.put(USER_KEY, user.id);
},
getUser : function(){
if(svcData.u === null){
DataFactory.getPrincipalName().then(function(adata){
DataFactory.getBDUser(adata.data.username).then(function(data){
var reg = {};
jsonHelper.setupRegistry(data.data,
reg);
jsonHelper.resolveReferences(
data.data, reg, 5);
console.log("Request is back");
svcData.u = data.data;
});
});
}
return svcData.u;
}
... snipped ...


In my controller, I do:

$scope.$watch($scope.user, function(newUser){
console.log($scope.user);
console.log("USER HERE");
doSomeStuff();
});
$scope.user = UserService.getUser();


The problem is that watch gets fired when I first assign
$scope.user
(it is null), then I get the console message "Request is back" but the watch function does not fire again.

Why, and how do I do this?

Answer
  1. Pass string to $watch()

    $scope.$watch('user', ...
    
  2. Break the function when newUser is invalid (null / undefined)

    if (!newUser){
      return;
    }
    
  3. Use promises

    Convert getUser() function to return a promise.

    For instance, https://plnkr.co/edit/nzq9O0JMTxn1k7FL9We5

    app.service('UserService', function($http, $q, $timeout) {
    
      var cachedUser = null;
    
      return {
        getUser: getUser
      }
    
      function getUser() {
        var def = $q.defer();
    
        if (cachedUser) {
          def.resolve(cachedUser)
        } else {
    
          // get user from cache. using timeout to simulate http response taking 2.5 seconds
    
          $timeout(function() {
    
            cachedUser = {
              name: 'Mr User'
            };
    
            def.resolve(cachedUser);
    
          }, 2500);
        }
    
        return def.promise;
      }
    });
    

For example:

$scope.$watch('user', function(newUser) {

  if (!newUser){
    return;
  }

  doSomeStuff();
});

UserService.getUser()
    .then(function(user){
         $scope.user = user
     });