Reputation: 1031
Fairly new to Angular, and struggling with Promises, Observables and async/await.
However, this doesn't seem to work. I have a feeling this has something to do with how Observables/subscribe works, but I am unable to solve it.
Code snippet:
initPage() {
fetchCurrentUserDetails().then((user) => { //tasks dependent on current user
//task 1
//task 2
});
}
fetchCurrentUserDetails(): Promise<any> {
return Promise.resolve((async () => {
let currentUser = this.global.getUser();// check if user is defined already
let userId: string = sessionStorage.getItem('userid');
if (currentUser == undefined) {
let initProfile = new Promise(resolve => resolve(this.fetchDetailsFromDB(userId)));
const profile: any = await initProfile; //Waits, but returns before the Observable comes back
let user = new User();
// initialize user with the fetched values
user.id = profile.id; // Undefined, since value not returned yet
user.name = profile.user_name; // Undefined, since value not returned yet
// Set this user in a global variable
this.global.setUser(user);
}
return this.global.getUser();
})());
}
fetchDetailsFromDB(userId: string) {
//callProfileService has nothing but the http.get statement
this.callProfileService(userId).subscribe((response) => {
let profile = response.body.response.data.user;
return profile;
});
}
Edit: adding how I tried with toPromise:
fetchDetailsFromDB(userId: string) {
this.callUserProfileService(userId).toPromise().then((response) => {
let profile = response.body.response.data.user;
return profile;
});
Is this the right way to do this? If so, how to make the await wait for the Observable to return?
Upvotes: 3
Views: 11564
Reputation: 15204
you can use callback
initPage() {
fetchCurrentUserDetails((user) => {
//task 1
//task 2
});
}
fetchCurrentUserDetails(callback) {
const currentUser = this.global.getUser();
if (!currentUser) {
const userId: string = sessionStorage.getItem('userid');
return this.callProfileService(userId).subscribe((response) => {
const profile = response.body.response.data.user;
let user = new User();
user.id = profile.id;
user.name = profile.user_name;
this.global.setUser(user);
return callback(user);
});
} else {
return callback(currentUser);
}
}
Upvotes: 2
Reputation: 350167
Indeed, you need the toPromise()
method, but don't forget to return that promise (the return
in the callback is not enough -- the function fetchDetailsFromDB
needs to return a promise).
On the rest of your code: it is an antipattern to use Promise.resolve
and new Promise
like that: as a rule of thumb, don't create a new promise with either of these when you already have a promise to work with (e.g. from an API function call).
So here is how you could do it with async
methods:
async fetchCurrentUserDetails(): Promise<any> {
//^^^^
let currentUser = this.global.getUser();
if (currentUser == undefined) {
const userId: string = sessionStorage.getItem('userid');
const profile: any = await this.fetchDetailsFromDB(userId);
currentUser = new User();
currentUser.id = profile.id;
currentUser.name = profile.user_name;
this.global.setUser(currentUser);
}
return currentUser;
}
async fetchDetailsFromDB(userId: string): Promise<any> {
const response = await this.callUserProfileService(userId).toPromise();
return response.body.response.data.user;
};
Upvotes: 6