It gets complicated to me when I mix the promise with subscribe and another async task together.
This is my auth service:
getCurrentUserToken(){
return new Promise((resolve,reject)=>{
firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {
resolve(idToken)
}).catch(function(error) {
reject(error)
});
})
}
This is my HTTP service:
sendEmail(email) {
return this.authService.getCurrentUserToken().then(token => {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Basic server-Password',
})
};
let data = email
data['idToken'] = token
return this.http.post(this.apiServer + 'sendEmail', data, httpOptions)
})
}
This is how I call the sendEmail(email)
function at the component:
Observable.fromPromise(this.httpService.sendEmail(element)).subscribe(
data3 => {
console.log(data3)
}, error => {
console.log(error)
}
))
I have to pass currentUserToken to the API to let the API authenticate the user session. Still, both of the the getCurrentUserToken()
sendEmail()
are running in async, so I have to use Promise
to pass the Token
to sendEmail()
function, and let the sendEmail function to call the API to send the email.
Without the promise, I am able to subscribe to the http.post
like this:
this.httpService.sendEmail(element).subscribe(
data3 => {
console.log(data3)
}, error => {
console.log(error)
}
))
Unfortunately, I screwed it up when I added the promise into it, and the console.log is returning this:
Observable {_isScalar: false, source: Observable, operator: MapOperator}
Please advise on how to subscribe to the http.post
that is placed inside the Promise
.
subscribe changes the type from Observable to Subscription , thus causing the type error. Make sure to create a completing pipe, like you can do with the first operator, otherwise the Promise will never resolve. You can leave out new Promise(...) in your consumer. Remove the new Promise call in your consumer.
race() : It waits until any of the promises is resolved or rejected. Promise. reject() : It returns a new Promise object that is rejected with the given reason. Promise. resolve() : It returns a new Promise object that is resolved with the given value.
So here is a simple answer to this question. Promises are used in Angular to resolve asynchronous operations, and Observables are used when the data comes from an external source like an API. Promises can be resolved with a single value or an array of values, and Observables emit one or more values over time.
There's seriously no need of Complicating things here.
I'll use async
/await
syntax here and for that, we'll have to work with Promise
s instead of Observable
s. Good thing is, we can leverage the toPromise()
method on an Observable
value to change it to a Promise
For getCurrentUserToken
getCurrentUserToken() {
return firebase.auth().currentUser.getIdToken(true);
// This will already return a Promise<string>
// So no need to do a .then and then return from there.
}
sendEmail
async sendEmail(email) {
// Since getCurrentUserToken returns a Promise<string> we can await it
const token = await this.authService.getCurrentUserToken();
// token will now have the Current User Token
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Basic server-Password',
})
};
let data = email
data['idToken'] = token
return this.http.post(this.apiServer + 'sendEmail', data, httpOptions).toPromise();
// Notice how we're calling the .toPromise() method here
// to change Observable into a Promise
}
This code will go in your Component Method where you were previously calling this.httpService.sendEmail
. DO MAKE SURE TO MARK THAT FUNCTION AS async
THOUGH.
// We can only await something in a function which is declared of type async
async sendEmail() {
try {
const data = await this.httpService.sendEmail(element);
// Since sendEmail again returns a Promise, I can await it.
console.log(data);
} catch (error) {
console.log(error);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With