首页 > 解决方案 > Angular10 - XHR 加载失败:POST - 浏览器阻止对同名域的 HTTP 请求

问题描述

我有一个由 Django REST API 和 Angular 10 前端 SPA 组成的网页。一般来说,我可以毫无问题地向我的后端发送 GET-、POST-、PUT- 和 DELETE-XHR 请求,我只有一个 API 端点,我的 SPA 请求以某种方式被明确地取消。该问题发生在 Chrome 和 Firefox 上,并且似乎与浏览器无关。我在谷歌浏览器中收到的错误消息是:

zone-evergreen.js:2845 XHR 加载失败:发布“https://www.aldrune.com/wiki1/api/timestamp/”。

这是我们掌握的相关信息:

  1. HTTP 请求在由浏览器或 SPA 构造后被取消(以下信息来自 chrome 网络选项卡) 在此处输入图像描述 在此处输入图像描述

  2. 在 chrome 的网络选项卡中重新启动 HTTP 请求会从后端返回正确的响应,证明 HTTP 请求对象构造正确 在此处输入图像描述

  3. 后端工作正常(基于 2. 并且我可以通过邮递员成功发送 HTTP 请求)

  4. 它不能与 CORS 相关,因为 SPA 和我的后端都是从同一个 HTTP Server (Apache2)提供的。即使这还不够,Django 当前配置为允许所有来源。

与此问题有关的其他问题的原因是无意的页面重新加载,从而中断了 AJAX 请求。但是当通过createTimestamp(). 该组件从字面上获取 HTML 所需的 2 个输入 DOM 元素,并构建要自己发送的对象。不涉及表单提交。

//session-audio.component.html
...
            <!-- Timestamp Create Form -->
            <div [ngClass]="{'d-none': !timestampCreateState, 'row my-1': timestampCreateState}">
                <input type="text" name="time" #timestampTimeInput />
                <input type="text" name="title" #timestampNameInput />
                <div>
                    <i class="icon hover-red fa fa-1-5x fa-times mx-1" (click)="cancelTimestampCreateState()"></i>
                    <i class="icon hover-green fa fa-1-5x fa-check mx-1" (click)="createTimestamp(timestampTimeInput, timestampNameInput)"></i>
                </div>
            </div>
...
//session-audio.component.ts
export class SessionAudioComponent implements OnInit {
...
  createTimestamp(timestampTimeInput: any, timestampNameInput: any){
    this.timestamp_model.time = this.stringToTime(timestampTimeInput.value);
    this.timestamp_model.name = timestampNameInput.value;
    //session_audio is set during initialization of this.timestamp_model

    this.timestampService.createTimestamp(this.timestamp_model).subscribe(timestamp => {
      this.timestamps.unshift(timestamp);
      this.timestampCreateState = false;
    }, error => console.log(error)).unsubscribe();
  }

}

我最好的猜测是它与组件有关,但是什么?

标签: javascriptangularajaxhttpxmlhttprequest

解决方案


该错误确实是由请求被中断引起的,在这种情况下是由于 observable 在它甚至可以完成向后端发出请求之前被取消订阅。问题发生在createTimestamp()我的组件的功能中。我在订阅中省略了回调函数以强调我的观点::

 this.timestampService.createTimestamp(this.timestamp_model).subscribe(...).unsubscribe();

课程:

不要在订阅后立即取消订阅 observable。那打断你的电话。

如果你想在获得第一个值后取消订阅的单次使用 Observable,请使用到处推荐的默认方法:使用pipe带有操作符的 rxjs 方法first()

  createTimestamp(timestampTimeInput: any, timestampNameInput: any){
    this.timestamp_model.time = this.stringToTime(timestampTimeInput.value);
    this.timestamp_model.name = timestampNameInput.value;
    //session_audio is set during initialization of this.timestamp_model

    this.timestampService.createTimestamp(this.timestamp_model).pipe(first()).subscribe(timestamp => {
      this.timestamps.unshift(timestamp);
      this.timestampCreateState = false;
    }, error => console.log(error));
  }

推荐阅读