简体   繁体   中英

How to turn off eventlistener in factory method which is returning promise to controllers?

I have a loginService factory used to perform login, logout and provide user data to controllers. Because I need to update userdata in controllers every time loginstate changes, my factory method is returning an update promise:

app.controller('TestCtrl', function ($scope, loginService) {
    loginService.currentUserData().then(null, null, function(CurrUserData){
        $scope.CurrUserData = CurrUserData;
    });
});

In loginService I'm listening to $firebaseSimpleLogin:login/logout events and after they're fired, I pass the userdata object (returned by function based on UID) or null ($fbSimpleLogin:logout event) to $emit. And finally, in my loginService.currentUserData() method I'm listening to this emitted events and returning deferred.notify(userdata/null).

First issue is that when I change the view (template+ctrl+location), I need to invoke $firebaseSimpleLogin:login/logout event to deliver my userData to new controller. Now, I'm doing it by $locationChangeStart event, but there should be better way...

And last issue: when I'm changing the view, there are more data calls, than I expectet. Probably every controller add event listeners on $rootScope by calling loginService.currentUserData()? Described code below:

$rootScope.$on('$firebaseSimpleLogin:login', function (e, authUser) {
    findUserByUid(authUser.uid);
});
$rootScope.$on('$firebaseSimpleLogin:logout', function() {
    $rootScope.$emit('userLogout', null);
});
$rootScope.$on('$locationChangeStart', function(event, next, current) { 
    currentUser().then(function(u){ 
        $timeout(function() { // without this same event on viewchange is fired
// by simplelogin, collision (I need to replace this whole block with invoking simpleloginevent)
            if (u) {$rootScope.$emit('$firebaseSimpleLogin:login', u);
            } else {$rootScope.$emit('$firebaseSimpleLogin:logout', null);};
        }, 150);
    });
});
function findUserByUid (uid) {
    var query = $firebase(usersRef.startAt(uid).endAt(uid));
    query.$on('loaded', function () {
        var username = query.$getIndex()[0];
        setCurrentUser(username);
    });
}
function setCurrentUser (username) {
    if (username) {$rootScope.$emit('userData', $firebase(usersRef).$child(username));};
}
var currentUserData = function () { // this method is used in CTRLs
    var deferred = $q.defer();
    var uDl = $rootScope.$on('userData', function(e, FbUserData){deferred.notify(FbUserData); });
    var uLl = $rootScope.$on('userLogout', function(){deferred.notify(null); });
    return deferred.promise;
};

I recently wrote a demo AngularFire app that has similar functionality. The way I found to handle this is only worry about three points.

  1. When the user logs in $rootScope.$on('$firebaseSimpleLogin:$login')

  2. When the user logs out $rootScope.$on('$firebaseSimpleLogin:$logout')

  3. Calling $getCurrentUser()

This will be able to capture the login life cycle. Since you need to know who the current user is, you can rely on the $firebaseSimpleLogin method rather than trying to $emit your own events.

You also could resolve the current user in the $routeProvider for each view. This way each view won't be rendered until the user has been loaded.

Here's the plunker project and the example Factory: http://plnkr.co/edit/M0UJmm?p=preview

// Auth factory that encapsulates $firebaseSimpleLogin methods
// provides easy use of capturing events that were emitted
// on the $rootScope when users login and out
.factory('Auth', function($firebaseSimpleLogin, Fb, $rootScope) {
  var simpleLogin = $firebaseSimpleLogin(Fb);
  return {
    getCurrentUser: function() {
      return simpleLogin.$getCurrentUser();
    },
    login: function(provider, user) {
      simpleLogin.$login(provider, {
        email: user.email,
        password: user.password
      });
    },
    logout: function() {
      simpleLogin.$logout();
    },
    onLogin: function(cb) {
      $rootScope.$on('$firebaseSimpleLogin:login',
        function(e, user) {
          cb(e, user);
        });
    },
    onLogout: function(cb) {
      $rootScope.$on('$firebaseSimpleLogin:logout',
        function(e, user) {
          cb(e, user);
        });
    }
  }
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM