可以取消 HttpClient GET 请求吗?

Possible to cancel HttpClient GET request?

我 运行 一个内部 Angular 项目,我想在其中引入一个 "Cancel Request" 按钮。我们有一个带有一堆参数的搜索功能,但这些请求最多可能需要两位数的秒数(10 秒及以上)。通常,当有人在搜索字段中输入过于明确的内容时,就会发生这种情况,因为我们会进行 LIKE/contains 搜索。

我希望能够取消这些请求,因此我的代码在返回到组件时不会执行。这样,我可以快速取消请求并发送新请求。

现在我将按钮设置为禁用,因此用户无法轻松发送新请求。如果我不这样做,就会出现以下问题:

  1. 发送request_1
  2. 发送request_2
  3. request_2 在 3 秒内完成并在页面上显示结果
  4. request_1 在 10 秒内完成并替换页面上的结果

显然这不是最优的。

要尝试的代码(单击 Get stuff 按钮,出现取消按钮):https://stackblitz.com/edit/angular-cgmyvc

不确定这是否适用于 promises(可能不应该适用),但使用 RxJS 和 Angular 的 HttpClient 就像取消订阅一样简单:

// to send
const requestSubscription = this.httpClient.get(/* ...args */);

// to cancel
requestSubscription.unsubscribe();

为了能够取消请求,您应该首先停止将 observable 转换为 Promise 并改为使用订阅。

您的服务应该是:

export class TestService {
  constructor(private http: HttpClient) { }

  public GetStuff() {
    return this
      .http
      .get("https://jsonplaceholder.typicode.com/todos/1")
  }
}

现在它 returns 是一个 observable 而不是 promise。

然后在你的组件中:

export class AppComponent  {
  constructor(private service: TestService){}
  public request;
  public Result;
  public GettingStuff = false;

  async ngOnInit() {

  }

  public GetStuff() {
    this.GettingStuff = true;
    this.request = this.service.GetStuff().subscribe((res) => {
      this.Result = JSON.stringify(res);
      this.GettingStuff = false;
    })
  }

  public async CancelGettingStuff() {
    console.log('cancelled');
    this.request.unsubscribe();
    this.GettingStuff = false;
  }
}

如你所见,我将订阅放入变量 request。如果有必要取消请求 - 我们只需调用 unsubscribe 方法。 这是工作 stackblitz。 我建议在测试之前通过开发人员工具模拟慢速互联网。

每次按 cancel 按钮,您都会看到请求被取消。

你必须像这样导入它:

import { Subscription } from 'rxjs/Subscription';

编辑Angular 6

import { Subscription } from 'rxjs';



import { Component } from '@angular/core';
import { TestService } from './services/test-service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  constructor(private service: TestService){}
  public Result;
  public GettingStuff = false;
    res: Subscription;
  async ngOnInit() {

  }

  public async GetStuff() {
    this.GettingStuff = true;

     this.res = await this.service.GetStuff(); 
    console.log(this.res);
    this.Result = JSON.stringify(this.res);

    this.GettingStuff = false;
  }

  public async CancelGettingStuff() {
    this.res.unsubscribe();
    this.GettingStuff = false;
  }
}

希望这对你有用。

您可以使用 switchMap 运算符,它会自动取消订阅之前的可观察对象。

可以参考这个stackblitz