0

I am trying to write a simple signup method and the followings are the codes I used:

ClientSide_codes,auth.servise.ts:

   checkUserExistence(user : User) : any {
    this.http.get<UserResponse>(baseURL + 'users/findUser')
    .subscribe(res => {
      if(res.success){
        console.log('user founded!');
        return true;
      }
    },
    err => {
      console.log('A problem happened: ', err);
      this.destroyUserCredentials();
      return false;
    });
  }


   signUp(user: any): Observable<any> {
    if (this.checkUserExistence(user) === false) {
      return this.http.post<RegResponse>(baseURL + 'users/signup',
      {'username': user.username, 'password': user.password, 'firstname' : user.firstname, 'lastname': user.lastname})
      .pipe( map(res => {
          this.storeUser({username: user.username});
          return {'success': true, 'username': user.username };
      }),
       catchError(error => this.processHTTPMsgService.handleError(error)));

    }
    else{
      console.log('This user already exists!');
      return ;
    }

  }

signup.component.ts:

export class SignupComponent implements OnInit {

  user = {username: '', password: '', firstname: '', lastname: '', remember: false};
  errMess: string;

  constructor(public dialogRef: MatDialogRef<SignupComponent>,
    private authService: AuthService) { }

  ngOnInit() {
  }

  onSubmit() {
    console.log('User: ', this.user);
    this.authService.signUp(this.user)
      .subscribe(res => {
        if (res.success) {
          this.dialogRef.close(res.success);
        } else {
          console.log(res);
        }
      },
      error => {
        console.log(error);
        this.errMess = error;
      });
  }

}

BackEnd-codes, usersRouter.js:

usersRouter.post('/signup', cors.corsWithOptions, (req, res, next) => {
  User.register(new User({username: req.body.username}), 
    req.body.password,  (err, user) => {
    if(err) {
      res.statusCode = 500;
      res.setHeader('Content-Type', 'application/json');
      res.json({err: err});
    }
    else {
      user.password = req.body.password;
      if (req.body.firstname)
        user.firstname = req.body.firstname;
      if (req.body.lastname)
        user.lastname = req.body.lastname;
      if (req.body.admin)
        user.admin = req.body.admin;        
      user.save((err, user) => {
        if (err) {
          res.statusCode = 500;
          res.setHeader('Content-Type', 'application/json');
          res.json({err: err});
          return next(err);
        }
        passport.authenticate('local')(req, res, () => {
          res.statusCode = 200;
          res.setHeader('Content-Type', 'application/json');
          res.json({success: true, status: 'Registration Successful!'});
        });
      });
    }
  });
});

And when I try to signup a new user and I know the user doesn't exist, it gives me following errors:

This user already exists!
core.js:5873 ERROR TypeError: Cannot read property 'subscribe' of undefined
    at SignupComponent.onSubmit (signup.component.ts:34)
    at SignupComponent_Template_form_ngSubmit_7_listener (signup.component.html:13)
    at executeListenerWithErrorHandling (core.js:21685)
    at wrapListenerIn_markDirtyAndPreventDefault (core.js:21727)
    at SafeSubscriber.schedulerFn [as _next] (core.js:36900)
    at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
    at SafeSubscriber.next (Subscriber.js:122)
    at Subscriber._next (Subscriber.js:72)
    at Subscriber.next (Subscriber.js:49)
    at EventEmitter.next (Subject.js:39)
defaultErrorLogger @ core.js:5873
handleError @ core.js:5926
handleError @ core.js:13548
executeListenerWithErrorHandling @ core.js:21688
wrapListenerIn_markDirtyAndPreventDefault @ core.js:21727
schedulerFn @ core.js:36900
__tryOrUnsub @ Subscriber.js:183
next @ Subscriber.js:122
_next @ Subscriber.js:72
next @ Subscriber.js:49
next @ Subject.js:39
emit @ core.js:36819
onSubmit @ forms.js:6253
NgForm_submit_HostBindingHandler @ forms.js:6294
executeListenerWithErrorHandling @ core.js:21685
wrapListenerIn_markDirtyAndPreventDefault @ core.js:21727
(anonymous) @ platform-browser.js:934
invokeTask @ zone-evergreen.js:400
onInvokeTask @ core.js:41235
invokeTask @ zone-evergreen.js:399
runTask @ zone-evergreen.js:168
invokeTask @ zone-evergreen.js:481
invokeTask @ zone-evergreen.js:1596
globalZoneAwareCallback @ zone-evergreen.js:1622
auth.service.ts:54 user founded!
Hasani
  • 3,543
  • 14
  • 65
  • 125

1 Answers1

0

this function checkUserExistence(user) is doing some asynchronous task, and you are checking the result returned from it

so, this if condition if (this.checkUserExistence(user) === false) is not checked properly, goes to the else part, which has a return statement but not returning an observable to be subscribed in the signUp component

I suggest you to define a new property of type BehaviorSubject, and it should return a Boolean, and give it an initial value = false

isUserExist = new BehaviorSubject<Boolean>(false);

checkUserExistence(user : User) : any {
    this.http.get<UserResponse>(baseURL + 'users/findUser')
    .subscribe(res => {
        if (res.success) {
            console.log('user founded!');
            // return true;
            this.isUserExist.next(true);
        }
    },
    err => {
    console.log('A problem happened: ', err);
        this.destroyUserCredentials();
        // return false;
        this.isUserExist.next(false);
    });
}

signUp(user: any): Observable<any> {
  return this.http.post<RegResponse>(baseURL + 'users/signup',
  {'username': user.username, 'password': user.password, 'firstname' : user.firstname, 'lastname': user.lastname})
  .pipe( map(res => {
      this.storeUser({username: user.username});
      return {'success': true, 'username': user.username };
  }),
    catchError(error => this.processHTTPMsgService.handleError(error)));
}

and check if the user exists or not in the component before calling the signup method from the service, so you will call it only if the user does not exist, by this, you will get rid of returning a non-observable response from the service, so you will do the signup only if the user does not exist (and this check is to be done in the component)

onSubmit() {
  console.log('User: ', this.user);
  // subscribe to the behavior subject we defined and emitted in the service, If it's false, then do the signup
  this.authService.isUserExist.subscribe((userExists: Boolean) => {
    // call the signup method only if the userExists is not true
    if (!userExists) {
      this.authService.signUp(this.user)
      .subscribe(res => {
        if (res.success) {
          this.dialogRef.close(res.success);
        } else {
          console.log(res);
        }
      }, error => {
        console.log(error);
        this.errMess = error;
      });
    }
  });
}
Mohammed Yousry
  • 2,134
  • 1
  • 5
  • 7