Prabhu Arumugam Prabhu Arumugam - 11 months ago 91
TypeScript Question

Angular2 Service Subscribe not working

Hi I cannot store data into UserDetailsArr object , PFB code for your reference.

User Details Class:

export class UserDetails
{
userId:string;
userName:string;
password:string;
firstName:string;
lastName:string;
mobileNumber:string;
email:string
}


Service Class:

import {Component} from '@angular/core'
import {OnInit} from '@angular/core'
import {UserService} from './user.service'
import {User} from './user'
import {UserDetails} from './user'
import {UserDetailComponent} from './user-detail.component'
import {HTTP_PROVIDERS} from '@angular/http';

@Component(
{
selector:'user-list',
template: `
<br/><br/><br/>
<div>
<table border='1'>
<thead>
<tr>
<th>First Name </th>
<th>Last Name </th>
<th>Mobile Number </th>
<th>Email </th>
</tr>
</thead>
<tr *ngFor="let user of UserDetailsArr">
<td> <span (click)="showDetails(user)"> {{user.firstName}} </span> </td>
<td> {{user.lastName}} </td>
<td> {{user.mobileNumber }} </td>
<td> {{user.email}} </td>
</tr>
</table>
</div>
<user-detail *ngIf = "selectedUser != null" [user] = "selectedUser"></user-detail>
<br/><br/><br/>

`,
providers:[UserService , HTTP_PROVIDERS],
directives:[UserDetailComponent]
}
)
export class UserListComponent implements OnInit
{
users:User[];
UserDetailsArr: UserDetails[]= [];
errorMessage: string = '';
isLoading: boolean = true;
public selectedUser = null;
constructor(private _userService:UserService)
{

}

ngOnInit():any
{
this.getUsers();
}

getUsers()
{

this._userService.getUsers()
.subscribe(
/* happy path */ p => this.UserDetailsArr = p,
/* error path */ e => this.errorMessage = e,
/* onComplete */ () => this.isLoading = false);


console.log(this.UserDetailsArr);
}

showDetails(user)
{
this.selectedUser = user;
}



}


web Service is working perfecltly If I log like below,

this._userService.getUsers()
.subscribe(
/* happy path */ p => console.log(JSON.stringify(p),
/* error path */ e => this.errorMessage = e,
/* onComplete */ () => this.isLoading = false));


user data has logged in browser console.

[{"UserId":"bcb444aa-401b-48a7-b1bf-17b4bf78b834","UserName":"prabhu","Password":"pwd","FirstName":"PRABHU","LastName":"ARUMUGAM","MobileNumber":"1234567890","Email":"prabhu@gmail.com"},
{"UserId":"d9e5ba40-d0d7-4d90-89b0-7e26660cc84b","UserName":"senthil","Password":"pwd","FirstName":"SENTHIL","LastName":"KUMAR","MobileNumber":"1234567890","Email":"senthil@gmail.com"},
{"UserId":"a59dabad-5a8c-4ced-9006-2181bf8c10cb","UserName":"vijay","Password":"pwd","FirstName":"VIJAY","LastName":"RAJ","MobileNumber":"1234567890","Email":"vijay@gmail.com"},
{"UserId":"f3e2d351-9413-4d80-8623-36556d27f875","UserName":"thamizh","Password":"pwd","FirstName":"THAMIZH","LastName":"VANAN","MobileNumber":"1234567890","Email":"thamizh@gmail.com"}]
(e) { return _this.errorMessage = e; } () { return _this.isLoading = false; }


But if I assign the data to UserDetailsArr data is not assigned,

this._userService.getUsers()
.subscribe(
/* happy path */ p => this.UserDetailsArr = p,
/* error path */ e => this.errorMessage = e,
/* onComplete */ () => this.isLoading = false);
console.log(this.UserDetailsArr);


Next line I tried to print but its not working, result is undefined :-(

Please help me out.. :-(.. Sorry for long post...

Answer Source

Observables call the callbacks passed to subscribe(...) or other operators like map(...) when data arrives.

The code after subscribe(...) is called immediately afterwards and as @JbNizet mentioned this is usually long before data arrives.

You need to move code that depends on the data received from the observable into one of the callbacks like:

 this._userService.getUsers()
       .subscribe(
            /* happy path */ p => {
                this.UserDetailsArr = p;
                console.log(this.UserDetailsArr);
            }),
             /* error path */ e => this.errorMessage = e,
             /* onComplete */ () => this.isLoading = false);