web-dev-qa-db-ja.com

保留中のすべてのHTTPリクエストをキャンセル/登録解除する方法angular 4+

保留中のすべてのHTTPリクエストをキャンセル/中止する方法angular 4+。

HTTPリクエストをキャンセルするunsubscribeメソッドがありますが、保留中のリクエストをすべて一度にキャンセルする方法があります。

特にルート変更中。

私がやったことが一つあります

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

しかし、これをグローバルに達成する方法

何か案は?

27
Sibiraj

RxJSから takeUntil() 演算子をチェックアウトして、サブスクリプションをグローバルに削除します。

-RxJS 6+(pipe構文を使用)

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

基本的に、next()を使用して、一連のストリームを完了するたびに、サブスクライブ解除Subjectでイベントを発行できます。また、メモリリークを回避するために、コンポーネントが破棄されるときにアクティブなObservableのサブスクライブを解除することをお勧めします。

読む価値があります :

43
Alexis Facques

インターセプターを作成して、すべてのリクエストに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).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()
  }
})
24
Bladito

すべてのサブスクリプションを手動でサブスクライブ解除したくない場合は、これを行うことができます。

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

ただし、サブスクリプションをコンポーネントプロパティとして保存する必要があります。コンポーネントから移動すると、AutoUnsubscribe機能が発生します。

9
Anton Lee

要求された機能の必要性は確信していませんが、フレームワークのhttpサービスをラップして委任することで、いつでもどこでも未処理の要求をすべてキャンセルし、これを実現できます。

ただし、このサービスを実装しようとすると、問題がすぐに明らかになります。一方で、ストックAngular httpクライアントを活用するサードパーティコードを含む既存のコードの変更を避けたいと思います。一方、実装の継承は避けたいと思います。

両方の世界を最大限に活用するために、ラッパーで実装 Angular Httpサービスを利用できます。既存のコードは、変更せずに機能し続けます(コードが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[] = [];
}

interfaceclassおよびCancellationAwareHttpClient宣言はマージされることに注意してください。このようにして、クラスimplementsHttpは、interface宣言のextends句によります。

今、私たちはサービスを提供します

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

既存のフレームワークが提供するサービスをオーバーライドする方法に注意してください。ファクトリーを使用してインスタンスを作成し、インジェクターのサイクルを回避するために、DIのデコレーターをラッパー自体に追加しません。

2
Aluan Haddad

ngOnDestroyコールバックは通常、インスタンスが破棄されたときに発生する必要があるカスタムクリーンアップに使用されます。

どこでリクエストをキャンセルしますか?

ブラウザの近くでリクエストをキャンセルしたい場合は、創造的なアイデアがあります here

2
Vala Khosravi

これを試して :

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

保留中の要求のリストを保持するカスタムHttpサービス(HttpClientを使用)を作成できます。 Http/HttpClientの代わりにこのカスタムサービスをhttpで起動すると、サブスクリプションがリストにプッシュされ、応答が返されるとそのサブスクリプションがポップされます。これを使用すると、すべての不完全なサブスクリプションがリストに表示されます。

同じカスタムサービスで、コンストラクターにルーターを挿入し、それをサブスクライブして、ルート変更イベントを取得します。このオブザーバブルが発行されるときはいつでも、リストにあるすべてのサブスクリプションのサブスクリプションを解除し、そこからすべての要素をポップするだけです。

コードスニペットが必要な場合は、コメントに記載してください。

0
Sumit Agarwal