angular - 将队列添加到 Angular 的 HttpClient

标签 angular observable

我有与 Add queueing to angulars $http service 中提到的完全相同的要求但需要使用 HttpInterceptor 在 Angular 4.3 或 5 中实现来自 @angular/common/http .

我有一个非常古怪的 API,它一次只能处理一个特定浏览器 session 的请求。因此,我需要确保每次在同一 session 中发出请求时,它都会进入一个队列,并且该队列一次执行一个请求,直到它为空。

最佳答案

解决方案

@Zlatko 提出了正确的方法,尽管其中几乎没有逻辑和语法问题,但我已将其更正并粘贴在工作代码下方:

import { Injectable } from '@angular/core';
import { Response } from '@angular/http';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject'

export class PendingRequest {
  url: string;
  method: string;
  options: any;
  subscription: Subject<any>;

  constructor(url: string, method: string, options: any, subscription: Subject<any>) {
    this.url = url;
    this.method = method;
    this.options = options;
    this.subscription = subscription;
  }
}

@Injectable()
export class BackendService {
  private requests$ = new Subject<any>();
  private queue: PendingRequest[] = [];

  constructor(private httpClient: HttpClient) {
    this.requests$.subscribe(request => this.execute(request));
  }

  /** Call this method to add your http request to queue */
  invoke(url, method, params, options) {
    return this.addRequestToQueue(url, method, params, options);
  }

  private execute(requestData) {
    //One can enhance below method to fire post/put as well. (somehow .finally is not working for me)
    const req = this.httpClient.get(requestData.url)
      .subscribe(res => {
        const sub = requestData.subscription;
        sub.next(res);
        this.queue.shift();
        this.startNextRequest();
      });
  }

  private addRequestToQueue(url, method, params, options) {
    const sub = new Subject<any>();
    const request = new PendingRequest(url, method, options, sub);

    this.queue.push(request);
    if (this.queue.length === 1) {
      this.startNextRequest();
    }
    return sub;
  }

  private startNextRequest() {
    // get next request, if any.
    if (this.queue.length > 0) {
      this.execute(this.queue[0]);
    }
  }
}

可以使用/调用上述服务以下方式进行 HTTP 调用(来自任何其他组件或服务)(显然您需要在组件中注入(inject) BackendService,例如在组件的提供者中提及并在构造函数中定义):
    this.backendService.invoke('https://jsonplaceholder.typicode.com/posts', 'Get', null, null)
    .subscribe(
      result => {
        this.data = result;
      }
    );

如果有人想看看正在工作的 plunker,那么 here is the working plunker .

关于angular - 将队列添加到 Angular 的 HttpClient,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48021728/

相关文章:

angular - 如何一个接一个地执行函数?

javascript - Angular 6 : Property 'fromEvent' does not exist on type 'typeof Observable'

javascript - TypeScript - 一次又一次调用 API 端点,直到得到所需的结果 - 递归还是循环?

rxjs - 什么触发了 combineLatest?

android - AsyncTask 中的可观察/订阅者

interface - Angular2 beta,一直使用接口(interface)未定义的属性

angular - 改变ThisBreaksApplicationSecurity angular2

javascript - 从另一个组件更改组件的属性并将其呈现在 angular 2 的 html 中

typescript - 当用户登录(auth 不为 null )时,如何在 AngularFire2 中获取对象?

ajax - Angular 2/4 & RxJS - forEach 内的订阅 - 确保流量控制在所有 Observable 完成之前不会继续