'Angular: data only available in subscribe method, but not outside

What is the best way to pass data from an http request to another component. I have programmed a user service here, which receives information about a user. Now I want to retrieve this in my login component. When I output the User Object to the console, console.log(this.user) returns undefined. Why is this and how can I solve the problem?

user.service.ts

@Injectable({ providedIn: 'root' })
export class UserService {
    user: User;

    constructor(private http: HttpClient) {}

    fetchUserByUsername(username: string){
        this.http
        .get<User>('http://localhost:8080/user/getByUsername?username=' + username)
        .subscribe(data => {
            this.user = data;
        });
        return this.user;
    }
}

login.component.ts

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css'],
  providers:[UserService]
})
export class LoginComponent {
  hide = true;
  user: User;

  constructor(private userService: UserService) { }

  validate() {
    this.user = this.userService.fetchUserByUsername('bonguen');
    console.log(this.user)
  }
}


Solution 1:[1]

You should always return the Observable or Promise from your service. You should not persist the data in the service

@Injectable({ providedIn: 'root' })
export class UserService {
    
    constructor(private http:HttpClient) {}

    fetchUserByUsername(username:string) {
      return this.http.get<User>('http://localhost:8080/user/getByUsername', { queryParams: { username } });
    }
}

In the component

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent {
  hide = true;
  user:User;

  constructor(private userService: UserService) { }

  validate() {
    this.userService.fetchUserByUsername('bonguen').subscribe(user => {
      this.user = user;
      console.log(this.user);
    }
  }
}

Solution 2:[2]

the api call is async so return this.user; gets called before the API gets finished loading, that's why you're getting undefined value . to solve this issues , so the subscription from the login component like

  validate() {
this.userService.fetchUserByUsername('bonguen').subscribe((res)=>{
  console.log(res , 'user')
})

here is a working example https://stackblitz.com/edit/angular-service-h6x2bp?file=app%2Flogin%2Flogin.component.ts

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Florian Gössele
Solution 2 Faizal Hussain