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

alp*_*ric 6 promise observable typescript angular

有三个按钮:

在此输入图像描述

单击第一个Request HTTP Data As Promise按钮将获取其 HTTP 响应,格式为Promise.

第二个Request HTTP Data As Observable按钮的响应为Observable.

这两个按钮都使用异步响应机制来获取响应。

现在,我希望第三个Request HTTP Data and Wait按钮能够获得同步响应。我希望它等待 http 服务返回 HTTP 响应。

怎么可能呢?以下是 Stackblitz 项目的链接(请使用脚本getDataSynchronous中定义的占位符函数HttpService来实现此功能):

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 []
  }
Run Code Online (Sandbox Code Playgroud)

pc_*_*der 8

演示异步函数是通过事件循环异步操作的函数,使用隐式 Promise 返回其结果。但使用异步函数的代码的语法和结构更像使用标准同步函数。wait 运算符用于等待 Promise。它只能在异步函数内使用。

getDataSynchronous() {
    return  this.http.get(this.jsonFile).toPromise()
}
Run Code Online (Sandbox Code Playgroud)

在组件中

async requestDataAndWait() {
    let httpData = await this.http.getDataSynchronous();  
    this.addMessages(httpData)  
}
Run Code Online (Sandbox Code Playgroud)

  • 这里没有必要分配“data”或“await”(因此也有“async”)——这些都不会改变“getDataSynchronous”**不是同步**的事实,实际上返回值的“promise”,并且因此可以实现 `getDataSynchronous() { return this.http.get(this.jsonFile).toPromise() }`。 (11认同)

Wil*_*lor 8

虽然这对于 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');
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这不能使用 Angular HTTP 客户端来完成,而且除非绝对必要,否则不应使用此解决方案,因为在大多数现代浏览器中,XmlHttpRequest主线程上的同步已被弃用。

  • 我想指出的是,笼统地说“不要这样做”不利于编程思维。想象一个前端应用程序,其 api 是有状态/无头的。您_必须_在发出许多请求之前发送获取 CSRF 令牌的请求。说“只是不这样做”意味着您将所有表单请求嵌套在回调中 - 这很丑陋、麻烦,而且一般来说更难维护。我可以想到更多同步请求也完全可以接受的场景。一般来说,当然,不要采取同步快捷方式。然而,有些情况下它完全没问题。 (3认同)