2
votes

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 []
  }
6
But why? It blocks the only thread. - Phix
I just want to know how to do it in Angular. - alphanumeric

6 Answers

4
votes

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)  
}
3
votes

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.

1
votes

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()
  }
0
votes

You can accomplish that by using async and await

async getDataSynchronous() {
  let data = await this.http.get(this.jsonFile).toPromise();
  return data;
}
0
votes

You can't, not with Javascript.

0
votes

You can try out a typescript library called ts-sync-request.

GitHub: https://github.com/VeritasSoftware/ts-sync-request

NPM: https://www.npmjs.com/package/ts-sync-request

You can make synchronous http calls from typescript using this library.

Eg:

GET

import { SyncRequestClient } from 'ts-sync-request/dist'
let id = 1;
let url = "http://localhost:59039/api/Movies/" + id;
 
let response = new SyncRequestClient()
                             .addHeader("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDc2OTg")
                        .get<Movie>(url);