简体   繁体   English

如何在Angular 8或9同步HTTP请求(发出请求等待)

[英]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 .单击第一个Request HTTP Data As Promise按钮获得其 HTTP 响应作为Promise

The second Request HTTP Data As Observable button gets its response as an Observable .第二个Request HTTP Data As Observable按钮将其响应作为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.现在,我想要第三个Request HTTP Data and Wait按钮获得同步响应。 I would like it to wait for the http service to return the HTTP response.我希望它等待 http 服务返回 HTTP 响应。

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):这是 Stackblitz 项目的链接(请使用HttpService脚本中定义的占位符 function getDataSynchronous来实现此功能):

https://stackblitz.com/edit/angular-ivy-ukgwct?file=src%2Fapp%2Fhttp.service.ts 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.演示异步 function 是一个 function,它通过事件循环异步操作,使用隐式 Promise 返回其结果。 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. await 运算符用于等待 Promise。它只能在异步 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 :尽管 Angular 不是惯用的,但您可以使用同步 XHR 请求在技术上实现这一点:

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 .请注意,它不能使用 Angular HTTP 客户端来完成,并且除非绝对必要,否则您不应该使用此解决方案,因为在大多数现代浏览器中,主线程上的同步XmlHttpRequest已被弃用。

This is working for me.这对我有用。

Write this code in your app.component.ts file:在您的app.component.ts文件中写入此代码:

  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:并像下面这样创建同步注销 function:

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

You can try out a typescript library called ts-sync-request .您可以试用一个名为ts-sync-request的 typescript 库。

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

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

You can make synchronous http calls from typescript using this library.您可以使用此库从 typescript 进行同步 http 调用。

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您可以通过使用asyncawait来实现

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

You can't, not with Javascript.你不能,不能用 Javascript。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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