拦截器在API中进行两次调用

时间:2017-08-13 21:00:58

标签: angular angular2-http

我正在开展一个项目并且一切运行良好......当我向API请求某些内容时(如下例所示),它显然只发送一个请求:

this.httpClient.get<MyInterface>('my_api').subscribe(data => this.items = data);

但是我想在新的HttpClient中利用拦截器,所以我开始搜索示例,然后找到了this

我已经定义了帖子中的所有内容:

进展-interceptor.ts

@Injectable()
export class ProgressInterceptor implements HttpInterceptor {

  progress$: Observable<number | null>;
  private progressSubject: Subject<number | null>;

  constructor() {
    this.progressSubject = new ReplaySubject<number | null>(1);
    this.progress$ = this.progressSubject.asObservable();
  }

  intercept<T>(req: HttpRequest<T>, next: HttpHandler): Observable<HttpEvent<T>> {
    const reportingRequest = req.clone({ reportProgress: true });
    const handle = next.handle(reportingRequest);

    handle.subscribe((event: HttpEvent<T>) => {
      switch (event.type) {
        case HttpEventType.Sent:
          this.progressSubject.next(undefined);
          break;

        case HttpEventType.DownloadProgress:
        case HttpEventType.UploadProgress:
          if (event.total) {
            this.progressSubject.next(Math.round((event.loaded / event.total) * 100));
          }
          break;

        case HttpEventType.Response:
          this.progressSubject.next(100);
          break;

        default:
        break;
      }
    });

    return handle;
  }
}

进展-component.ts

export class ProgressComponent implements OnInit {

  progressPercentage$: Observable<number>;

  @Input() color: ProgressBarColor = 'primary';

  @ViewChild(MdProgressBar) private progressBar: MdProgressBar;

  constructor(private interceptor: ProgressInterceptor) { }

  ngOnInit(): void {
    this.progressPercentage$ = this.interceptor.progress$
        .map(progress => {
          if (isNil(progress)) {
            this.setMode('indeterminate');

            return 0;
          } else {
            this.setMode('determinate');

            return progress;
          }
        });
  }

  private setMode(mode: ProgressBarMode) {
    this.progressBar.mode = mode;
  }
}

app.module.ts

const interceptor = new ProgressInterceptor();

@NgModule({
  // ...
  providers: [
    { provide: ProgressInterceptor, useValue: interceptor },
    { provide: HTTP_INTERCEPTORS, useValue: interceptor, multi: true }
  ]
})

问题是:现在,使用这个拦截器,当我做任何请求时,它会两次点击API。为什么?我怀疑是因为subscribe intercept()内的ProgressInterceptor

如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

您的猜测是正确的,通过订阅拦截器内的句柄,您再次触发可观察链,从而再次触发API调用。

在您的情况下,相应的运算符为library = [ {title: "Hitch Guide", by: "Doug", cats: ["comedy", "fiction", "british"]}, {title: "P and P", by: "Jane", cats: ["morality", "fiction", "british"]}, {title: "Searchin'", by: "Chad", cats: ["non-fiction", "morality", "gps"]}, {title: "Crazy Ben", by: "Walt", cats: ["non-fiction", "comedy", "dads"]} ] # => [{:title=>"Hitch Guide", :by=>"Doug", :cats=>["comedy", "fiction", "british"]}, # {:title=>"P and P", :by=>"Jane", :cats=>["morality", "fiction", "british"]}, # {:title=>"Searchin'", :by=>"Chad", :cats=>["non-fiction", "morality", "gps"]}, # {:title=>"Crazy Ben", :by=>"Walt", :cats=>["non-fiction", "comedy", "dads"]}] library.each_with_object({}) do |g,h| title = g[:title] g[:cats].each { |c| (h[c] ||= []) << title } end #=> {"comedy"=>["Hitch Guide", "Crazy Ben"], # "fiction"=>["Hitch Guide", "P and P"], # "british"=>["Hitch Guide", "P and P"], # "morality"=>["P and P", "Searchin'"], # "non-fiction"=>["Searchin'", "Crazy Ben"], # "gps"=>["Searchin'"], # "dads"=>["Crazy Ben"]} see the docs),因为您只想观察链内发生的事情,但无意操纵其中的任何内容。

看起来应该是这样的:

Node, X, Y, Z, Stress_data
1, 1.0, 1.0, 1.0, 123
2, 2.0, 2.0, 2.0, 234
3, 3.0, 3.0, 3.0, 345
...

Faces
1, 2, 3
3, 4, 5
...