How to make synchronous HTTP request in Angular 8 or 9 (make a request and wait)

26,184

Solution 1

Demo An asynchronous function is a function that operates asynchronously via the event loop, using an implicit Promise to return its result. But the syntax and structure of your code using async functions are much more like using standard synchronous functions. The await operator is used to wait for a Promise. It can only be used inside an async function.

getDataSynchronous() {
    return  this.http.get(this.jsonFile).toPromise()
}

in component

async requestDataAndWait() {
    let httpData = await this.http.getDataSynchronous();  
    this.addMessages(httpData)  
}

Solution 2

Although is not idiomatic to Angular, you could technically achieve this using a synchronous XHR request:

getDataSynchronous() {
    var request = new XMLHttpRequest();
    request.open('POST', `${environment.userApiUrl}/logout`, false);  // `false` 
    makes the request synchronous
    request.send({});

    if (request.status === 200) {
        return request.response;
    } else {
        throw new Error('request failed');
    }
}

Note that it cannot be done using Angular HTTP Client, and also that you should not use this solution unless absolutely necessary as synchronous XmlHttpRequest on the main thread is deprecated in most modern browsers.

Solution 3

This is working for me.

Write this code in your app.component.ts file:

  ngOnInit(): void
  {
    window.addEventListener('beforeunload', (e) =>
    {
      this.logoutAndWait();
    })
  }

  async logoutAndWait()
  {
    const httpData = await this.userService.logoutSynchronous();
  }

and create a sync logout function like this below:

  logoutSynchronous()
  {
    return this.http.post<string>(`${environment.userApiUrl}/logout`, {}, { withCredentials: true }).toPromise()
  }
Share:
26,184

Related videos on Youtube

alphanumeric
Author by

alphanumeric

Updated on July 05, 2022

Comments

  • alphanumeric
    alphanumeric almost 2 years

    There are three buttons:

    enter image description here

    Clicking the first Request HTTP Data As Promise button gets its HTTP response as a Promise.

    The second Request HTTP Data As Observable button gets its response as an Observable.

    Both these buttons get their responses using asynchronous response mechanism.

    Now, I would like the third Request HTTP Data and Wait button to get a synchronous response. I would like it to wait for the http service to return the HTTP response.

    How could it be done? Here is the link to the Stackblitz project (please use the placeholder function getDataSynchronous defined in the HttpService script to implement this functionality):

    https://stackblitz.com/edit/angular-ivy-ukgwct?file=src%2Fapp%2Fhttp.service.ts

    export class HttpService {
      jsonFile = '../assets/products.json';
    
      constructor(private http: HttpClient) {}
    
      getDataAsPromise(): Promise<any> {
        return this.http.get(this.jsonFile)
          .toPromise()
      }
    
      getDataAsObservable(): Observable<any> {
        return this.http.get(this.jsonFile)
      }
    
      getDataSynchronous(): any {
        return []
      }
    
    • Phix
      Phix almost 4 years
      But why? It blocks the only thread.
    • alphanumeric
      alphanumeric almost 4 years
      I just want to know how to do it in Angular.
  • jonrsharpe
    jonrsharpe almost 4 years
    There's no point assigning data or having await (and therefore async) here - none of that changes the fact that getDataSynchronous is not synchronous, actually returns a promise of the value, and can therefore be implemented getDataSynchronous() { return this.http.get(this.jsonFile).toPromise() }.
  • jonrsharpe
    jonrsharpe almost 4 years
  • Paulo Pedroso
    Paulo Pedroso over 3 years
    Thanks for the help. I am using a mock to develop offline and I needed to read a file synchrounously in order to do some sorting and filtering.
  • Nate I
    Nate I over 3 years
    I'd like to point out that a blanket statement of "just don't do it" is not conducive to a programming mindset. Think of a front-end app whose api is stateful/headless. You have to send a request to get a CSRF token before many requests. To say "just don't do it" implies that you'd nest all your form requests within a callback -- that's ugly, cumbersome, and generally speaking less maintainable. I can think of more scenarios where a synchronous request is perfectly acceptable as well. Generally, sure, don't take the synchronous shortcut. However, there are cases where it's perfectly fine.
  • Will Taylor
    Will Taylor over 3 years
    @NateI your example is not a good one. What if the request takes a long time and the user tries to switch tabs in the browser? What if I want to show an animated loading spinner while the request is in progress? Neither of these things will work, as a synchronous HTTP request will block the browser's UI thread. And if maintainability is a concern we can use async/await for synchronous looking code. IMO it would be a very rare occasion to find a scenario in JavaScript where synchronous HTTP request was the better option.
  • Nate I
    Nate I over 3 years
    I mean, this has been discussed thousands of times and is not a mystery by any stretch of the imagination. Calling the synchronous request on a worker will not block the UI thread or cause hitching/freezing, and is essentially the same as async/await. The question asked how to accomplish a synchronous request, and async/await is not synchronous. Neither is a synchronous request on a worker (within the worker it is, so other logic awaiting completion could live there and truly be 'synchronous'), but you asked ;)
  • Nate I
    Nate I over 3 years
    The bottom line is: Provide an answer and an explanation. There's absolutely zero reason to be condescending and dogmatic. Telling anyone "just don't do it" provides zero context and is not helpful in any manner. Had you simply stated in your answer what is listed on the deprecation warning for synchronous requests, you'd have provided actual value instead of a dogmatic, opinionated answer which will be ignored by roughly 99% of devs. The question was how to accomplish a synchronous request, and there are cases out there which call for it (whether you like this fact or not).
  • Will Taylor
    Will Taylor over 3 years
    @nate-i fair point, I have reworded the answer.
  • Janos Vinceller
    Janos Vinceller almost 3 years
    This does not make it synchronous. Observables and async methods are not synchronous, so there's no use in trying to interchange them. At the end of the they, you got data if it was successful in some near or later future and you won't if it wasn't. It's a better idea to design your application to be asynchronous and then make use of those asyncronousness.