AngularJS - Firebase - Promise Error

318 views Asked by At

I am trying to follow a basic tutorial on thinkster.io and am tunning into issues. https://thinkster.io/learn-to-build-realtime-webapps/ The tutorial uses an depreciated SimpleLogin, so I have changed the code accordingly however I keep getting an error as follows.

TypeError: Cannot read property 'finally' of undefined at Scope.$scope.register (http://localhost:9000/scripts/controllers/auth.js:9:31)

I believe the issue is with the promise in my controller logic. It keeps returning undefined? Any help would be appreciated. I can add more info depending on what people think. Thank You

SERVICE LOGIC

'use strict';

app.factory('Auth', function ($firebaseAuth, $rootScope) {
  var ref = new Firebase('https://park-reservation.firebaseio.com/');
  //var auth = $firebaseSimpleLogin(ref);

  var Auth = {
    register: function (user) {
      return ref.createUser({
        email: user.email,
        password: user.password
      }, function(error, userData) {
        if (error) {
          switch (error.code) {
            case 'EMAIL_TAKEN':
              console.log('The new user account cannot be created because the email is already in use.');
              break;
            case 'INVALID_EMAIL':
              console.log('The specified email is not a valid email.');
              break;
            default:
              console.log('Error creating user:', error);
          }
        } else {
          console.log('Successfully created user account with uid:', userData.uid);
        }
      });
    },
    login: function (user) {
      return ref.authWithPassword({
        email: user.email,
        password: user.password
      }, function(error, authData) {
        if (error) {
          console.log('Login Failed!', error);
        } else {
          console.log('Authenticated successfully with payload:', authData);
        }
      });
    },
    logout: function () {
      ref.unauth();
    },
    resolveUser: function() {
      return ref.getAuth();
    },
    signedIn: function() {
      return !!Auth.user.provider;
    },
    user: {}
  };

  $rootScope.$on('login', function(e, user) {
    console.log('logged in');
    angular.copy(user, Auth.user);
  });
  $rootScope.$on('logout', function() {
    console.log('logged out');
    angular.copy({}, Auth.user);
  });

  return Auth;
});

CONTROLLER LOGIC

app.controller('AuthCtrl', function ($scope, $location, Auth, user) {
  if (user) {
  //  $location.path('/');
  }

  $scope.register = function () {
    Auth.register($scope.user).finally(function() {
      return Auth.login($scope.user).finally(function() {
        $location.path('/');
      });
    });
  };
});
1

There are 1 answers

0
ShankarSangoli On BEST ANSWER

createUser and authWithPassword method of Firebase do not return anything so calling finally method on an undefined value will throw an error.

You should add a new parameter (a callback function) to each register and login method which should be called once the Firebase method responds.

Change in the service

  register: function (user, cb) {
      return ref.createUser({
        email: user.email,
        password: user.password
      }, function(error, userData) {
        if (error) {
          switch (error.code) {
            case 'EMAIL_TAKEN':
              cb('The new user account cannot be created because the email is already in use.');
              break;
            case 'INVALID_EMAIL':
              cb('The specified email is not a valid email.');
              break;
            default:
              cb('Error creating user:', error);
          }
        } else {
          //Successfully created user account
          cb(null, userData.uid);
        }
      });
    },
    login: function (user, cb) {
      return ref.authWithPassword({
        email: user.email,
        password: user.password
      }, function(error, authData) {
        if (error) {
          //Login failed
          cb(error);
        } else {
          cb(null, authData);
        }
      });
    },

Change in the controller

  $scope.register = function () {
    Auth.register($scope.user, function(err, userId) {
      if (err) {
        //show error 
        return;
      }
      //You can add the userId returned by register method to user object
      $scope.user.Id = userId;
      Auth.login($scope.user, function(err, authData) {
        if (err) {
          //show error 
          return;
        }
        $location.path('/');
      });
    });
  };