【问题标题】:Is there a way to "subscribe" to an array variable changes in Angular?有没有办法“订阅”Angular中的数组变量更改?
【发布时间】:2020-06-09 17:15:06
【问题描述】:

我正在寻找一种等待用户停止交互然后发出 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 列表。

当我尝试快速连续选择多个关键字时出现问题,因为这会触发每次点击更新suggestedKeywords列表的请求,所以我想使用debounceTime()来阻止请求触发,直到用户停止单击项目一段时间;然而,据我所知,这需要一个 Observable 来改变元素,但就我而言,它只是一个简单的数组。

是否有办法跟踪数组的值,以便在它发生变化后等待一段时间,然后再发出 HTTP 请求,比如 Observable?

编辑:使用了 cmets 中建议的 from() 运算符,为了真正收听更改,我需要定义其他方法吗?我在想类似于FormControls 中的valueChanges()

查看更多文档,我倾向于SubjectBehaviorSubject 等;但我不确定这是否是一个正确的方法,谁能提供一个如何做到这一点的例子?

【问题讨论】:

  • 您是否尝试过使用 from([]) 运算符将数组转换为 observable?
  • @Bozhinovski 不知道这是什么东西,我会试试看它是否适合我
  • 希望对您有所帮助。快乐编码

标签: javascript angular typescript rxjs debouncing


【解决方案1】:

我最终做的是使用 Subject 来跟踪更改,调用它的 next() 函数 evrytime 修改 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));
  }

}

【讨论】:

    【解决方案2】:

    将你的数组包裹在 Observable.of() RxJS 操作符中,它的行为就像 observable 一样

    【讨论】:

    • 当你说像 observable 一样的“行为”时,你的意思是什么?我已经尝试过了,但我猜 当值更改时通知 的部分由我决定?你知道我应该怎么做吗?
    • 然后你可以在 BehaviorSubject 变量中设置你的数组仍然会表现得像 observable,当收到新值时你可以发出它们
    猜你喜欢
    • 2019-09-15
    • 2021-12-29
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 2017-10-13
    • 2016-11-24
    相关资源
    最近更新 更多