Angular 如何取消/取消订阅所有挂起的HTTP请求;

Angular 如何取消/取消订阅所有挂起的HTTP请求;,angular,typescript,rxjs,angular-http-interceptors,Angular,Typescript,Rxjs,Angular Http Interceptors,如何取消/中止所有挂起的HTTP请求 有一个取消HTTP请求的unsubscribe方法,但是如何一次取消所有挂起的请求 尤其是在路线改变的时候 我做了一件事 ngOnDestroy() { this.subscription.unsubscribe(); } 但如何在全球范围内实现这一目标 有什么想法吗?ngondestory回调通常用于实例销毁时需要进行的任何自定义清理 您想在哪里取消您的请求 如果您想取消浏览器关闭上的请求,则可能存在创造性想法如果您不想手动取消所有订阅,则可以执行以

如何取消/中止所有挂起的HTTP请求

有一个取消HTTP请求的
unsubscribe
方法,但是如何一次取消所有挂起的请求

尤其是在路线改变的时候

我做了一件事

ngOnDestroy() {
  this.subscription.unsubscribe();
}
但如何在全球范围内实现这一目标


有什么想法吗?

ngondestory
回调通常用于实例销毁时需要进行的任何自定义清理

您想在哪里取消您的请求


如果您想取消浏览器关闭上的请求,则可能存在创造性想法如果您不想手动取消所有订阅,则可以执行以下操作:

export function AutoUnsubscribe(constructor) {

  const original = constructor.prototype.ngOnDestroy;

  constructor.prototype.ngOnDestroy = function() {
    for (const prop in this) {
      if (prop) {
        const property = this[prop];
        if (property && (typeof property.unsubscribe === 'function')) {
          property.unsubscribe();
        }
      }
    }

    if (original && typeof original === 'function') {
      original.apply(this, arguments)
    };
  };

}
然后,您可以将其用作组件中的装饰器

@AutoUnsubscribe
export class YourComponent  {
}
但是您仍然需要将订阅存储为组件属性。 当您导航出组件时,将出现自动取消订阅功能。

请尝试以下操作:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Rx';

export class Component implements OnInit, OnDestroy {
    private subscription: Subscription;
    ngOnInit() {
        this.subscription = this.route.params.subscribe();
    }
    ngOnDestroy() {
        this.subscription.unsubscribe();
    }
}
从RxJS签出操作员以全局删除订阅:

-RxJS 6+(使用
管道
语法)

从'rxjs/operators'导入{takeUntil};
导出类组件{
受保护的ngUnsubscribe:Subject=新主题();
[...]
公共httpGet():void{
this.http.get()
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe((数据)=>{…});
}
公共Ngondestory():void{
//这将中止所有HTTP请求。
this.ngUnsubscribe.next();
//这就很好地完成了这个主题。
this.ngUnsubscribe.complete();
}
}
-RxJS<6

import 'rxjs/add/operator/takeUntil'

export class YourComponent {
   protected ngUnsubscribe: Subject<void> = new Subject<void>();

   [...]

   public httpGet(): void {
      this.http.get()
         .takeUntil(this.ngUnsubscribe)
         .subscribe( (data) => { ... })
   }

   public ngOnDestroy(): void {
       this.ngUnsubscribe.next();
       this.ngUnsubscribe.complete();
   }
}
导入'rxjs/add/operator/takeUntil'
导出类组件{
受保护的ngUnsubscribe:Subject=新主题();
[...]
公共httpGet():void{
this.http.get()
.takeUntil(this.ngUnsubscribe)
.subscribe((数据)=>{…})
}
公共Ngondestory():void{
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
}
每次您想要完成一组流时,基本上都可以使用
next()
在取消订阅
主题上发出一个事件。当组件被破坏时,取消订阅活动的可观察对象也是一种很好的做法,以避免内存泄漏

值得一读:


您可以创建自定义Http服务(使用HttpClient),该服务维护挂起请求的列表。无论何时启动http服务,而不是http/HttpClient,现在都将订阅推送到列表中,并在返回响应时弹出该订阅。使用此选项,您将拥有列表中所有未完成的订阅

现在,在同一个定制服务中,在构造函数中注入路由器并订阅它以获取路由更改事件。现在,每当这个可观察对象发出时,您所需要做的就是取消订阅列表中的所有订阅,并弹出列表中的所有元素


如果您需要代码片段,请务必在注释中提及。

我不认为需要请求的功能,但您可以实现这一点,通过包装框架的http服务并委托给它,随时随地取消所有未完成的请求

然而,当我们着手实现这项服务时,问题很快就会显现出来。一方面,我们希望避免更改现有代码,包括利用http客户端的第三方代码。另一方面,我们希望避免实现继承

为了充分利用这两个方面,我们可以使用包装器实现Angular
Http
服务。现有代码将继续工作而不做任何更改(前提是所述代码不做任何愚蠢的事情,如使用http
http实例)


请注意我们是如何覆盖现有框架提供的服务的。我们使用工厂来创建实例,并且不向包装器本身添加任何DI装饰器,以避免注入器中出现循环。

您可以创建一个拦截器,对每个请求应用
takeUntil
操作符。然后在路由更改时,您将发出取消所有挂起请求的事件

@Injectable()
export class HttpCancelInterceptor implements HttpInterceptor {
  constructor(private httpCancelService: HttpCancelService) { }

  intercept<T>(req: HttpRequest<T>, next: HttpHandler): Observable<HttpEvent<T>> {
    return next.handle(req).pipe(takeUntil(this.httpCancelService.onCancelPendingRequests()))
  }
}
最后,将拦截器注册到你的app.module.ts:

  import { HttpCancelInterceptor } from 'path/to/http-cancel.interceptor';
  import { HTTP_INTERCEPTORS } from '@angular/common/http';

  @NgModule({
    [...]
    providers: [
      {
        multi: true,
        provide: HTTP_INTERCEPTORS,
        useClass: HttpCancelInterceptor
      }
    ],
    [...]
  })
  export class AppModule { }

为@Bladito-answer添加了一些几乎完美的东西

实际上,HttpCancelService堆栈是完美的,但问题在于它的调用位置。如果您有子路由,则在导航端调用此选项可能会导致问题

因此,我制作了一个抽象容器组件,当HttpCancelService被销毁时调用它。这样,当我想要更精细地剪切任何Http取消请求时,我就可以进行管理

从'@angular/core'导入{Component,OnDestroy,OnInit};
从“../../services/http cancel service.service”导入{HttpCancelService};
@组成部分({
选择器:“某个抽象容器”,
模板:`
抽象组件
`,
样式URL:['./抽象容器.component.scss']
})
导出类AbstractContainerComponent实现OnInit、OnDestroy{
构造函数(受保护的只读httpCancelService:httpCancelService){}
ngOnInit(){}
ngOnDestroy():void{
此.httpCancelService.cancelPendingRequests()文件;
}
}
这是一个具体的组件,扩展了抽象组件:

从'@angular/core'导入{Component,OnInit};
从“../../../shared/components/abstract container/abstract container.component”导入{AbstractContainerComponent};
从“../../../shared/services/http cancel service.service”导入{HttpCancelService};
@组成部分({
选择器:“一些混凝土容器”,
templateUrl:'.some concrete container.component.html',
styleURL:['./一些具体的容器.component.scss']
})
导出类SomeConcreteContainerComponent扩展了AbstractContainerComponent的OnInit实现{
构造函数(受保护的只读httpCancelService:httpCancelService){
超级(httpCan)
import {NgModule} from '@angular/core';
import {ConnectionBackend, RequestOptions} from '@angular/http';

import CancellationAwareHttpClient from 'app/services/cancellation-aware-http-client';

let cancellationAwareClient: CancellationAwareHttpClient;

const httpProvider = {
  provide: Http,
  deps: [ConnectionBackend, RequestOptions],
  useFactory: function (backend: ConnectionBackend, defaultOptions: RequestOptions) {
    if (!cancellationAwareClient) {
      const wrapped = new Http(backend, defaultOptions);
      cancellationAwareClient = new CancellationAwareHttpClient(wrappedHttp);
    }
    return cancellationAwareClient;
  }
};

@NgModule({
  providers: [
    // provide our service as `Http`, replacing the stock provider
    httpProvider,
    // provide the same instance of our service as `CancellationAwareHttpClient`
    // for those wanting access to `cancelOutstandingRequests`
    {...httpProvider, provide: CancellationAwareHttpClient}
  ]
}) export class SomeModule {}
@Injectable()
export class HttpCancelInterceptor implements HttpInterceptor {
  constructor(private httpCancelService: HttpCancelService) { }

  intercept<T>(req: HttpRequest<T>, next: HttpHandler): Observable<HttpEvent<T>> {
    return next.handle(req).pipe(takeUntil(this.httpCancelService.onCancelPendingRequests()))
  }
}
@Injectable()
export class HttpCancelService {
  private cancelPendingRequests$ = new Subject<void>()

  constructor() { }

  /** Cancels all pending Http requests. */
  public cancelPendingRequests() {
    this.cancelPendingRequests$.next()
  }

  public onCancelPendingRequests() {
    return this.cancelPendingRequests$.asObservable()
  }

}
this.router.events.subscribe(event => {
  if (event instanceof ActivationEnd) {
    this.httpCancelService.cancelPendingRequests()
  }
})
  import { HttpCancelInterceptor } from 'path/to/http-cancel.interceptor';
  import { HTTP_INTERCEPTORS } from '@angular/common/http';

  @NgModule({
    [...]
    providers: [
      {
        multi: true,
        provide: HTTP_INTERCEPTORS,
        useClass: HttpCancelInterceptor
      }
    ],
    [...]
  })
  export class AppModule { }
    //This is the example of cancelling the get request once you leave the TestComponent.

    import { Component, OnInit} from '@angular/core';

    @Component({
      selector: 'app-test',
      templateUrl: './test.component.html'
    })
    export class TestComponent implements OnInit {

      request: any;
someList: any;

      constructor( private _someService: SomeService) {

      }

    ngOnInit() {
        this.getList();
      }

      ngOnDestroy(){
        this.request.unsubscribe(); // To cancel the get request.
      }

      getList() {
        this.request= this._someService.getAll()
          .subscribe((response: any) => {
            this.someList= response;
          }, (error) => {
            console.log("Error fetching List", error);
          })
      }

    }
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';

@UntilDestroy()
@Component({})
export class InboxComponent {
  ngOnInit() {
    interval(1000)
      .pipe(untilDestroyed(this))
      .subscribe();
  }
}