Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subscribe http.post that is placed inside a promise Angular 6

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.

like image 454
Jerry Avatar asked Oct 13 '18 16:10

Jerry


People also ask

Can we subscribe to Promise in Angular?

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.

What is resolve in Promise Angular?

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.

Should I use Promise in Angular?

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.


1 Answers

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 Promises instead of Observables. Good thing is, we can leverage the toPromise() method on an Observable value to change it to a Promise

Focus on my comments in the code as well

Here's the implementation

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.
}

For 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
}

How to use it?

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);
  }
}
like image 107
SiddAjmera Avatar answered Oct 13 '22 01:10

SiddAjmera