有没有办法把"subscribe"的一个数组变量改成Angular?

Is there a way to "subscribe" to an array variable changes in Angular?

我正在寻找一种方法来等待用户停止交互然后发出 HTTP 请求,为此我正在研究来自 RxJs 的 debounceTime() 运算符,但我的目标是等待的是我定义的数组。

场景是这样的:

export class KeywordSelectionComponent implements OnInit {

  constructor(private proposalService: ProposalService) { }

  @ViewChild(MatTable, {static: true}) kwTable: MatTable<any>;
  @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;
  @Input() proposalId: string;

  keywordInput = new FormControl(null, Validators.required);

  dataSource: MatTableDataSource<Keyword>;
  displayedColumns = ['action', 'keyword', 'searches', 'competition', 'cpc'];
  suggestedKeywords: Keyword[] = [];
  selectedKeywords: string[] = [];

  fetchSuggestions(seeds?: string[]) {
    const ideas = {
      seeds: [],
      limit: 25
    };
    this.proposalService.getKeywordIdeas(this.proposalId, ideas).pipe(retry(3)).subscribe(res => {
      this.suggestedKeywords = res;
    });
  }

}

我没有在这里包括整个组件,但想法如下:

我在页面上呈现了一个 suggestedKeywords 的列表,每个列表都应该调用一个 addKeyword() 方法来将该关键字添加到 dataSource,然后,我调用 fetchSuggestions() 方法来获取新关键字来填充 suggestedKeywords 列表。

当我尝试快速连续 select 多个关键字时,问题就来了,因为这会触发对每次点击更新 suggestedKeywords 列表的请求,所以我想使用debounceTime() 防止请求在用户停止点击项目之前触发;然而,据我所知,这需要一个 Observable 来改变元素,但在我的例子中,它只是一个简单的数组。

是否有某种方式可以跟踪数组的值,以便它在发出 HTTP 请求之前等待一段时间,就像 Observable 一样?

EDIT:按照评论中的建议使用了 from() 运算符,为了实际收听更改,我是否需要定义其他方法?我在想 FormControls.

中类似于 valueChanges() 的内容

阅读更多文档后,我倾向于 SubjectBehaviorSubject 等;但我不确定这是否是一种正确的方法,任何人都可以提供有关如何执行此操作的示例吗?

用 Observable.of() RxJS 运算符包裹你的数组,它的行为就像 observable

我最后做的是使用 Subject 来跟踪更改,调用它的 next() 函数每次修改 suggestedKeywords 数组并将其作为可观察对象订阅.

我的组件最终看起来像这样:

export class KeywordSelectionComponent implements OnInit {

  constructor(private proposalService: ProposalService) { }

  keywordInput = new FormControl(null, Validators.required);
  suggestedKeywords: Keyword[] = [];
  selectedKeywords: string[] = [];
  isLoadingResults = false;

  tag$ = new Subject<string[]>();

  ngOnInit() {
    this.tag$.asObservable().pipe(
      startWith([]),
      debounceTime(500),
      switchMap(seeds => this.getSuggestionsObservable(seeds))
    ).subscribe(keywords => {
      this.suggestedKeywords = keywords;
    });
  }

  addSuggestedKeyword(keyword: Keyword) {
    const suggestedKeyword = keyword;
    const existing = this.dataSource.data;

    if (!existing.includes(suggestedKeyword)) {
      existing.push(suggestedKeyword);
      this.dataSource.data = existing;
    }

    this.tag$.next(this.getCurrentTableKeywords());
  }

  fetchKeywordSearch(keyword: string) {
    this.isLoadingResults = true;
    this.keywordInput.disable();
    const search = {
      type: 'adwords',
      keyword
    };
    const currentData = this.dataSource.data;

    this.proposalService.getKeywordSearch(this.proposalId, search).pipe(retry(3)).subscribe(res => {
      currentData.push(res);
      this.dataSource.data = currentData;
    }, error => {},
    () => {
      this.isLoadingResults = false;
      this.keywordInput.enable();
      this.tag$.next(this.getCurrentTableKeywords());
    });
  }

  getCurrentTableKeywords(): string[] {}

  getSuggestionsObservable(seeds: string[] = []): Observable<Keyword[]> {
    const ideas = {
      type: 'adwords',
      seeds,
      limit: 25
    };

    return this.proposalService.getKeywordIdeas(this.proposalId, ideas).pipe(retry(3));
  }

}