首页 > 解决方案 > mat-autocomplete 多次调用服务器而不是一次

问题描述

当我键入几个字母时,它应该执行 GET 请求并自动完成返回的 JSON 对象。出于某种原因,我可以从我的 nodejs 控制台中看到,在我停止输入几秒钟而不是一次之后,它会像 3 次一样击中后端。(我有一个延迟计时器,用于检查用户是否完成输入)我的代码有什么问题?

<div id="userSearch">
  <mat-form-field class="formFields" id="username1Field" [ngStyle]="{'font-size.px': 12}" appearance="outline">
    <mat-label id="placeholder">Sender</mat-label>
    <input type="text" placeholder="Find User" name="username1" aria-label="Number" matInput [formControl]="myControl"
      (keyup)="onKeySearch($event)" [matAutocomplete]="auto" required>
    <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
      <mat-option *ngFor="let option of posts" [value]="option.username">
        {{option.username}}
      </mat-option>
    </mat-autocomplete>
    <mat-error>User Invalid</mat-error>

  </mat-form-field>
</div>

零件

import { Component, OnInit, OnDestroy, ViewChild } from "@angular/core";
import { AuthService } from "../auth.service";
import { Router } from "@angular/router";
import { MessagingService } from "../message-table/messaging.service";
import { FormControl } from "@angular/forms";
import { SubmitListingService } from "../submit-listing/submit-auction.service";
import { takeUntil } from "rxjs/operators";
import { Subject } from "rxjs";
import { FindUserModel } from "../header/user-search.model";
import { Complaint } from "../message-table/complaint.model";
import { MatTableDataSource, MatSort } from "@angular/material";

@Component({
  selector: "admin-analyzer",
  templateUrl: "./admin-analyzer.component.html",
  styleUrls: ["./admin-analyzer.component.css"]
})
export class AdminAnalyzerComponent implements OnInit, OnDestroy {
  constructor(
    private authService: AuthService,
    private router: Router,
    private messagingService: MessagingService,
    private submitListingService: SubmitListingService
  ) {}
  dataSource: MatTableDataSource<any> = new MatTableDataSource();
  userId: string;
  myControl = new FormControl();
  posts: FindUserModel[] = [];
  destroy = new Subject();
  timeout;
  getData = false;
  isLoading = false;
  currentPage = 1;
  searchedUserId: string;
  messages: Complaint[];
  foundUser = false;
  totalPosts: number;

  displayedColumns = ["defendant", "userThatSubmitted", "creationDate"];

  @ViewChild(MatSort, { static: false }) set sort(sort: MatSort) {
    this.dataSource.sort = sort;
  }

  ngOnInit() {
    this.userId = this.authService.getUserId();
  }

  readMessage(
    id: string,
    recipient: string,
    creatorName: string,
    creatorId: string
  ) {
    this.router.navigate(["/read-message", id], { skipLocationChange: true });
  }

  getComplaints() {
    this.isLoading = true;
    this.messagingService
      .getComplaints(this.searchedUserId, this.currentPage)
      .subscribe(res => {
        console.log(res);
        this.totalPosts = res.maxPosts;
        this.messages = res.posts;
        this.dataSource.data = this.messages;
        this.isLoading = false;
        this.getData = true;
      });
  }
  private onKeySearch(event: any) {
    var $this = this;

    this.timeout = setTimeout(function() {
      if (event.keyCode !== 13) {
        $this.executeListing(event.target.value);
      }
    }, 2000);

    for (const post of this.posts) {
      if (event.target.value === post.username) {
        console.log("ITS A MATCH!");
        this.foundUser = true;
        this.searchedUserId = post.id;
        console.log("searchedUserId2");
        console.log(this.searchedUserId);
        this.posts = [];
      }
    }
  }

  private executeListing(userSearched: string) {
    if (userSearched === "[Object object]") {
      return;
    }


    console.log(userSearched);
    if (userSearched.length > 2) {
      this.submitListingService
        .getUserIdAutoComplete(userSearched, this.userId)
        .pipe(takeUntil(this.destroy))
        .subscribe(res => {
          console.log("res");
          console.log(res);
          this.posts = res.posts;
          console.log(this.posts);
        });
    }
  }
  ngOnDestroy() {
    clearTimeout(this.timeout);
    this.destroy.next();
    this.destroy.complete();
  }
}

标签: angular

解决方案


您将onKeySearch侦听器附加到keyup事件,这意味着每次按键都会触发以下代码:

this.timeout = setTimeout(function() {
  if (event.keyCode !== 13) {
    $this.executeListing(event.target.value);
  }
}, 2000);

在创建新的超时之前,您需要清除已经存在的超时。即使this.timeout被覆盖,也只是超时 ID,而不是超时本身。

clearTimeout(this.timeout);
this.timeout = setTimeout(function() {
  if (event.keyCode !== 13) {
    $this.executeListing(event.target.value);
  }
}, 2000);

推荐阅读