简体   繁体   English

有没有办法“订阅”Angular 中的数组变量更改?

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

I'm looking for a way to wait for the user to stop interaction and then make an HTTP request, for this I'm looking into the debounceTime() operator from RxJs, but the target I'm waiting for is an array I defined.我正在寻找一种方法来等待用户停止交互然后发出 HTTP 请求,为此我正在研究来自 RxJs 的 debounceTime debounceTime()运算符,但我正在等待的目标是我定义的数组.

This is the scenario:这是场景:

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

}

I'm not including the whole component here, but the idea is the following:我没有在这里包括整个组件,但想法如下:

I have a list of suggestedKeywords which I render on the page, each of these should call an addKeyword() method to add that keyword to the dataSource , and after that, I call the fetchSuggestions() method to get new keywords to populate the suggestedKeywords list.我有一个在页面上呈现的suggestedKeywords关键字列表,每个都应该调用addKeyword()方法将该关键字添加到dataSource ,然后,我调用fetchSuggestions()方法来获取新关键字以填充suggestedKeywords关键字列表。

The problem comes when I try to select multiple keywords in quick succession, since that would trigger a request for each of those clicks to update the suggestedKeywords list, so I wanted to use the debounceTime() to prevent the request to trigger until the user stops clicking items for a bit;当我尝试快速连续选择多个关键字时,问题就出现了,因为这会触发每次点击更新suggestedKeywords关键字列表的请求,所以我想使用debounceTime()来防止请求触发,直到用户停止点击一下项目; however this requires an Observable to be the element changing as far as I know, but in my case, it is just a simple array.然而,据我所知,这需要一个 Observable 作为元素变化,但在我的情况下,它只是一个简单的数组。

Is there someway to keep track of the value of the array so it waits for a while after it changes before making the HTTP request, like an Observable?有没有办法跟踪数组的值,以便它在发出 HTTP 请求之前等待一段时间,例如 Observable?

EDIT : Used the from() operator as suggested in the comments, in order to actually listen to changes do I need to define other methods?编辑:按照评论中的建议使用from()运算符,为了实际听取更改,我是否需要定义其他方法? I'm thinking something similar to valueChanges() in FormControls .我在想类似于FormControls valueChanges()东西。

Going through more documentation I'm leaning towards Subject , BehaviorSubject , etc;通过更多的文档,我倾向于SubjectBehaviorSubject等; but I'm not sure if this would be a correct approach, could anyone provide an example on how to do this?但我不确定这是否是一种正确的方法,谁能提供一个关于如何做到这一点的例子?

将您的数组包装在 Observable.of() RxJS 运算符中,它将表现得像 observable

What I ended up doing was using a Subject to keep track of the changes, calling it's next() function evrytime a modified the suggestedKeywords array and subscribing to it as an observable.我最终做的是使用Subject来跟踪更改,调用它的next()函数,每次修改suggestedKeywords关键字数组并将其订阅为可观察的。

My component ended up looking like this:我的组件最终看起来像这样:

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM