简体   繁体   中英

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

There are three buttons:

在此处输入图像描述

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 []
  }

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

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 .

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

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);

You can accomplish that by using async and await

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

You can't, not with Javascript.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM