user12
user12

Reputation: 239

Wait for http request to complete in angular 4 service

This might be a basic question. but I am new to angular services(promises,observable etc).

basically, I have a button(login) in login page , once user clicks on that button I want to validate and generate token. once the token is assigned field on service, then I will redirect to some page(Home page). But what is happening now is, when I made a function call to angular service function, before it gets(asynchronously) the token itself my page is redirecting.


app-data-service

`

    import { Injectable } from '@angular/core';
    import { HttpClient,HttpHeaders } from '@angular/common/http';
    import 'rxjs/add/operator/map';
    import 'rxjs/add/operator/mergeMap';
    import 'rxjs/add/operator/toPromise';
    @Injectable()
    export class AppDataServiceService {
      tokenGenerated:any='';
      constructor(private http: HttpClient) { 

      }

      getData(){
        console.log("Started.. in service");
         this.http.get('http://host/url').toPromise()
         .then(this.extractData);

      }
      private extractData(res: Response) {
        console.log("completed.. in service");
        this.tokenGenerated=res;
        return res;
    }

    }
    `---------------------------------------------------
    login component

    import { Component, OnInit } from '@angular/core';
    import { AppDataServiceService } from '../app-data-service.service';
    import { Router } from '@angular/router';

    @Component({
      selector: 'app-login-component',
      templateUrl: './login-component.component.html',
      styleUrls: ['./login-component.component.css']
    })
    export class LoginComponentComponent implements OnInit {

      constructor(private dataService:AppDataServiceService,private router:Router) {

       }

      ngOnInit() {
      }

      submit(){
        this.dataService.getData();
        console.log('after executing service');
        this.router.navigate(['/view']);
      };

    }
-------------------------------------------------------------
   login html

<div class="container">
  <label><b>Username</b></label>
  <input type="text" placeholder="Enter Username" name="uname" >

  <label><b>Password</b></label>
  <input type="password" placeholder="Enter Password" name="psw" >



</div>

<input type="button" (click)='submit()'  value="Login"  name="submit"/>

console output in browser:

Started.. in service

after executing service

completed.. in service

Can you help me to let http call wait till its completion. I am not sure if that is the way to use promise to make the call synchronous.

Upvotes: 1

Views: 13665

Answers (2)

Use synchronous http request as below

var request = new XMLHttpRequest();
request.open('GET', "https://domain/api", false);  
request.send(null);
const response = JSON.parse(request.responseText); 

Would not be able to take advantage of DI using HttpClient and hence should be used absolutely when required.

Upvotes: 1

user184994
user184994

Reputation: 18281

You should return a promise (or Observable) from your service, and subscribe to that in the component.

Without doing so, the component has no way of knowing when your asynchronous code has finished executing, so it prints that log statement immediately

Change the service like so:

getData(){
    console.log("Started.. in service");
    return this.http.get('http://host/url').toPromise()
        .then(res => this.extractData(res));
}

Then in the component

submit(){
    this.dataService.getData().then(() => {
        console.log('after executing service');
        this.router.navigate(['/view']);
    };
};

Upvotes: 7

Related Questions