webentwicklung-frage-antwort-db.com.de

So können Sie alle ausstehenden HTTP-Anforderungen (Winkel 4+) abbrechen/abbestellen

So brechen Sie alle ausstehenden HTTP-Anforderungen (Winkel 4+) ab.

Es gibt eine unsubscribe-Methode, um HTTP-Anforderungen abzubrechen, aber wie alle ausstehenden Anforderungen gleichzeitig abgebrochen werden. 

Besonders während der Routenänderung.

Ich habe eines getan 

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

aber wie kann man das global erreichen?

Irgendwelche Ideen?

18
Sibiraj

Überprüfen Sie den Operator " takeUntil() " von RxJS, um Ihre Abonnements global zu löschen: 

- RxJS 6+ (mit der pipe-Syntax)

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

Sie können grundsätzlich ein Ereignis über Ihre Abmeldung Subject mit next() ausgeben, wenn Sie mehrere Streams abschließen möchten. Es empfiehlt sich außerdem, aktive Observables abzumelden, da die Komponente zerstört wird, um Speicherverluste zu vermeiden.

Lesenswert :

24
Alexis Facques

Sie können einen Interceptor erstellen, um den Operator takeUntil auf jede Anfrage anzuwenden. Bei der Routenänderung geben Sie dann einen Wert aus, der alle ausstehenden Anforderungen storniert.

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

  intercept<T>(req: HttpRequest<T>, next: HttpHandler): Observable<HttpEvent<T>> {
    return next.handle(req).takeUntil(this.httpCancelService.onCancelPendingRequests())
  }
}

Helfer Service.

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

}

Haken Sie die Route an einer beliebigen Stelle in Ihrer App ein (z. B. App-Komponente).

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

Wenn Sie nicht alle Abonnements manuell abbestellen möchten, können Sie Folgendes tun:

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

}

Dann können Sie es als Dekorateur in Ihrer Komponente verwenden

@AutoUnsubscribe
export class YourComponent  {
}

sie müssen jedoch weiterhin Subskriptionen als Komponenteneigenschaften speichern. Wenn Sie aus der Komponente heraus navigieren, wird die AutoUnsubscribe-Funktion ausgeführt.

10
Anton Lee

Ich bin nicht überzeugt, dass die geforderte Funktionalität erforderlich ist. Sie können dies jedoch tun, indem Sie alle ausstehenden Anforderungen jederzeit und an jedem beliebigen Ort abbrechen, indem Sie den http-Service des Frameworks verpacken und daran delegieren.

Bei der Implementierung dieses Dienstes wird jedoch schnell ein Problem sichtbar. Einerseits möchten wir vermeiden, dass der vorhandene Code geändert wird, einschließlich des Codes von Drittanbietern, der den aktuel- len Angular-http-Client nutzt. Andererseits möchten wir die Implementierungsvererbung vermeiden.

Um das Beste aus beiden Welten zu erhalten, können wir mit dem Wrapper implementieren den Angular Http-Service ausführen. Bestehender Code funktioniert auch ohne Änderungen weiter (vorausgesetzt, dieser Code führt zu nichts Dummem wie use http instanceof Http).

import {Http, Request, RequestOptions, RequestOptionsArgs, Response} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import {Subscription} from 'rxjs/Subscription';



export default interface CancellationAwareHttpClient extends Http { }

export default class CancellationAwareHttpClient {
  constructor(private wrapped: Http) {
    const delegatedMethods: Array<keyof Http> = [
      'get', 'post', 'put', 'delete',
      'patch', 'head', 'options'
    ];
    for (const key of delegatedMethods) {
      this[key] = wrapped[key].bind(wrapped);
    }
  }

  cancelOutstandingRequests() {
    this.subscriptions.forEach(subscription => {
      subscription.unsubscribe();
    });
    this.subscriptions = [];
  }

  request(url: string | Request, options?: RequestOptionsArgs) {
    const subscription = this.wrapped.request(url, options);
    this.subscriptions.Push(subscription);
    return subscription;
  }

  subscriptions: Subscription[] = [];
}

Beachten Sie, dass die Deklarationen interface und class für CancellationAwareHttpClient zusammengeführt werden. Auf diese Weise wird unsere Klasse implementiertHttp aufgrund der interface-Deklaration der extends-Deklaration.

Jetzt bieten wir unseren Service an

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 {}

Beachten Sie, wie wir den vorhandenen Framework-Service außer Kraft setzen. Wir verwenden eine Factory, um unsere Instanz zu erstellen, und fügen dem Wrapper selbst keine Dekoratoren für DI hinzu, um einen Zyklus im Injektor zu vermeiden.

2
Aluan Haddad

ngOnDestroy callback wird normalerweise für jede benutzerdefinierte Bereinigung verwendet, die bei der Zerstörung der Instanz erfolgen muss.

wo möchten Sie Ihre Anfrage stornieren?

vielleicht, wenn Sie Ihre Anfragen über den Browser stornieren möchten, gibt es eine kreative Idee hier

2
Vala Khosravi

Versuche dies :

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();
    }
}
2
Chandru
    //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);
          })
      }

    }
1
sanjil shakya

Sie können einen benutzerdefinierten HTTP-Service erstellen (mithilfe von HttpClient), der eine Liste ausstehender Anforderungen verwaltet. Wenn Sie diesen benutzerdefinierten Dienst anstelle von Http/HttpClient mit einem http feuern, pushen Sie jetzt die Subskriptionen in eine Liste, und bei Rückkehr des Antwort-Pops wird dieses Abonnement ausgegeben. Mit dieser Option werden alle unvollständigen Abonnements in einer Liste angezeigt. 

Jetzt im selben benutzerdefinierten Dienst Router in den Konstruktor einfügen und darauf abonnieren, um die Routenänderungsereignisse abzurufen. Immer wenn dieses Observable emittiert wird, müssen Sie nur noch alle in der Liste vorhandenen Subskriptionen abbestellen und alle Elemente aus dieser Liste entfernen.

Wenn Sie ein Code-Snippet benötigen, erwähnen Sie dies im Kommentar.

1
Sumit Agarwal