Angular API 调用每秒都会获取数据

问题描述 投票:0回答:1

我继承了一些 Angular/ng-boostrap 代码,这些代码定义了一个包含静态数据的表,可以正常工作。现在我们需要从 API 调用中获取数据,因此我尝试对其进行如下修改。我使用这个问题的答案作为基础

here是展示该问题的最小版本。 (https://stackblitz.com/~/github.com/cherfim/angular-problem如果链接不起作用,复制粘贴即可)

executions.service.ts 进行 API 调用的位置:

import { Injectable, PipeTransform } from '@angular/core';
import { DecimalPipe } from '@angular/common';
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
import { debounceTime, delay, map, switchMap, tap } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

interface SearchResult {
  jobs: any[];
  total: number;
}

interface State {
  page: number;
  pageSize: number;
  searchTerm: string;
  startIndex: number;
  endIndex: number;
  totalRecords: number;
}

const compare = (v1: string | number, v2: string | number) => v1 < v2 ? -1 : v1 > v2 ? 1 : 0;

/**
 * Table Data Match with Search input
 * @param  job field value fetch
 * @param term Search the value
 */
function matches(job: any, term: string, pipe: PipeTransform) {
  return true;
}

@Injectable({
  providedIn: 'root'
})

export class AdvancedService {
  fetchedJobs: any[] = [];
  fetchedJobs$: Observable<any[]>;
  private _loading$ = new BehaviorSubject<boolean>(true);
  private _search$ = new Subject<void>();
  private _jobs$ = new BehaviorSubject<any[]>([]);
  private _total$ = new BehaviorSubject<number>(0);
  private _state: State = {
    page: 1,
    pageSize: 10,
    searchTerm: '',
    startIndex: 0,
    endIndex: 9,
    totalRecords: 0
  };

  constructor(private pipe: DecimalPipe,
    private http: HttpClient) {

    this.fetchedJobs$ = this.http.get<any[]>(`https://api.publicapis.org/entries`).pipe(
      tap((res: any[])=>{
        this.fetchedJobs=res;
    }));

    this._search$.pipe(
      tap(() => this._loading$.next(true)),
      debounceTime(200),
      switchMap(() => this._search()),
      delay(200),
      tap(() => this._loading$.next(false))
    ).subscribe(result => {
      this._jobs$.next(result.jobs);
      this._total$.next(result.total);
    });
    this._search$.next();
  }

  /**
   * Returns the value
   */
  get jobs$() { return this._jobs$.asObservable(); }
  get total$() { return this._total$.asObservable(); }
  get loading$() { return this._loading$.asObservable(); }
  get page() { return this._state.page; }
  get pageSize() { return this._state.pageSize; }
  get searchTerm() { return this._state.searchTerm; }

  get startIndex() { return this._state.startIndex; }
  get endIndex() { return this._state.endIndex; }
  get totalRecords() { return this._state.totalRecords; }

  /**
   * set the value
   */
  set page(page: number) { this._set({ page }); }
  set pageSize(pageSize: number) { this._set({ pageSize }); }
  set startIndex(startIndex: number) { this._set({ startIndex }); }
  set endIndex(endIndex: number) { this._set({ endIndex }); }
  set totalRecords(totalRecords: number) { this._set({ totalRecords }); }
  set searchTerm(searchTerm: string) { this._set({ searchTerm }); }

  private _set(patch: Partial<State>) {
    Object.assign(this._state, patch);
    this._search$.next();
  }

  /**
   * Search Method
   */
  private _search(): Observable<SearchResult> {
    const { pageSize, page, searchTerm } = this._state;

    return this.fetchedJobs$.pipe(
      map((res: any[]) => {

      let jobs = Object.values(res);

      // 2. filter
      jobs = jobs.filter(job => matches(job, searchTerm, this.pipe));
      const total = jobs.length;

      // 3. paginate
      this.totalRecords = jobs.length;
      this._state.startIndex = (page - 1) * this.pageSize + 1;
      this._state.endIndex = (page - 1) * this.pageSize + this.pageSize;
      if (this.endIndex > this.totalRecords) {
        this.endIndex = this.totalRecords;
      }
      jobs = jobs.slice(this._state.startIndex - 1, this._state.endIndex);

      return  { jobs, total } as SearchResult;

    }));

  }
}


app.component.ts 订阅完成的地方:

import { Component, OnInit, ViewChildren, QueryList } from '@angular/core';
import { Observable } from 'rxjs';
import { AdvancedService } from './executions.service';
import { CommonModule, DecimalPipe } from '@angular/common';


@Component({
  selector: 'app-component',
  standalone: true,
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  imports: [CommonModule],
  providers: [AdvancedService, DecimalPipe]
})

/**
 * Datatable Component
 */
export class AppComponent implements OnInit {

  tables$: Observable<any[]>;
  total$: Observable<number>;
  testbooks: any[] = [];

  constructor(public service: AdvancedService) {
    this.tables$ = service.jobs$;
    this.total$ = service.total$;
  }

  ngOnInit(): void {

    this.tables$.subscribe((data: any) => {
      console.log(data.length);
      this.testbooks = data;
    });
  }
}

然后在模板中使用它

<div class="row">
    <div class="col-lg-12">
        <div class="card">
            <div class="card-body">
                <div class="table-responsive">
                    <table id="datatable" class="table table-bordered dt-responsive nowrap w-100 datatables">
                        <tbody *ngFor="let job of testbooks;let i=index;">
                            <tr>
                                <td>
                                    <div class="card">
                                        <div class="card-body">
                                            <h1>test</h1>

                                        </div>
                                    </div>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
            <!-- end card body -->
        </div>
        <!-- end card -->

    </div>
    <!-- end col -->
</div>
<!-- end row -->

我在浏览器控制台中看到他进行了调用,获取并显示了数据,我的问题是 API 被不停地调用,结果数据刷新(比如每秒一次)。

我做错了什么?

angular rxjs bootstrap-5 angular-ui-bootstrap
1个回答
0
投票

_search
中的
AdvancedService
方法中,您正在调用
totalRecords
endIndex
设置器(StackBlitz 中的第 118 行和第 122 行)。这些 setter 调用
_set
方法,该方法
next
_search$
主题,然后导致服务构造函数内的
_search$
流订阅运行。

我认为您在设置

next
_search$
startIndex
时不应该
endIndex
totalRecords
主题。

© www.soinside.com 2019 - 2024. All rights reserved.