typescript - Hur man avbryter/avprenumererar alla väntande HTTP-förfrågningar i Angular 4+


Hur man avbryter/stoppar alla väntande HTTP-förfrågningar i Angular 4+.

Det finns en unsubscribe-metod för att avbryta HTTP-förfrågningar men hur avbryter man alla väntande förfrågningar på en gång.

Speciellt under ruttändring.

Det finns en sak jag gjorde

ngOnDestroy() {
  this.subscription.unsubscribe();
}

men hur man uppnår detta globalt

Några idéer?

Svar #1

Kolla in takeUntil()-operatorn från RxJS för att globalt avsluta dina prenumerationer :

- RxJS 6+ (använder pipe-syntaxen)

import { takeUntil } from 'rxjs/operators';

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

   [...]

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

   public ngOnDestroy(): void {
       // This aborts all HTTP requests.
       this.ngUnsubscribe.next();
       // This completes the subject properlly.
       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();
   }
}

Du kan i princip sända ett event på ditt avregistrerings-Subject med next() varje gång du vill avsluta en mängd strömmar. Det är också god praxis att avregistrera aktiva Observables när komponenten förstörs, för att undvika minnesläckor.

Värt att läsa :

  • Undvika att ta tills läckor

  • Ett fantastiskt svar från seangwright

Svar #2

Du kan skapa en interceptorn för att tillämpa takeUntil-operatorn på varje begäran. Sedan, vid ruttändring, kommer du att skicka ett evenemang som avbryter alla väntande begäranden.

@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()))
  }
}

Hjälptjänst.

@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()
  }

}

Hook på ruttförändringar någonstans i din app (t.ex. onInit i appComponent).

this.router.events.subscribe(event => {
  if (event instanceof ActivationEnd) {
    this.httpCancelService.cancelPendingRequests()
  }
})

Och sist men inte minst, registrera interceptorn i din 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 { }

Svar #3

Om du inte vill avregistrera alla prenumerationer manuellt, kan du göra så här:

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)
    };
  };

}

Då kan du använda det som en dekoratör i din komponent

@AutoUnsubscribe
export class YourComponent  {
}

men du måste fortfarande lagra prenumerationer som komponentegenskaper. Och när du navigerar bort från komponenten kommer AutoUnsubscribe-funktionen att inträffa.

Relaterade artiklar