Angular等待http获取

Angular wait for http get

我目前正在开发 api 的前端,其中有一个输入字段,只要输入不是唯一的,我想验证该字段以禁用提交按钮。

我的组件看起来有点像这样:

export class CategoryCreateComponent implements OnInit {
  categoryNamesInUse: Category[];

  categoryCreateForm: FormGroup;

  constructor(private categoryService: CategoryService) {}

  ngOnInit(): void {
    this.getAllUsedNames();

    this.categoryCreateForm = new FormGroup({
      categoryName: new FormControl('', [
        Validators.required,
        Validators.minLength(1),
        this.invalidCategoryNames.bind(this),
      ]),
    });
  }    
  
  getAllUsedNames() {
    this.categoryService
      .findAllByUser()
      .pipe(
        map((categories) => {
          const usedNames = [];
          for (const key in categories) {
            usedNames.push(categories[key].name);
          }
          return usedNames;
        })
      )
      .subscribe((categoryNames) => (this.categoryNamesInUse = categoryNames));
  }
    
  invalidCategoryNames(control: FormControl): { [message: string]: boolean } {
    if (this.categoryNamesInUse.indexOf(control.value) !== -1) {
      return { categoryNameAlreadyInUse: true };
    }
    return null;
  }
}

问题是,categoryNamesInUse[] 未定义,我不知道如何等待我的 getAllUsedNames() 方法。

我猜你不会按字面意思分享你的代码,所以我不确定,但你可以定义一个布尔变量 (isSubmitButtonDisabled = true) 并移动这部分:

this.categoryCreateForm = new FormGroup({
      categoryName: new FormControl('', [
        Validators.required,
        Validators.minLength(1),
        this.invalidCategoryNames.bind(this),
      ]),
    });

进入这里:

.subscribe((categoryNames) => {
    this.categoryNamesInUse = categoryNames;
    --moved block--
    isSubmitButtonDisabled = false;
});

Ozan 的回答是正确的,但我会提供您可能更喜欢的 async / await 解决方案。

async ngOnInit(): Promise<void> {
    await this.getAllUsedNames();

    this.categoryCreateForm = new FormGroup({
      categoryName: new FormControl('', [
        Validators.required,
        Validators.minLength(1),
        this.invalidCategoryNames.bind(this),
      ]),
    });
  }

getAllUsedNames(): Promise<void> {
    return new Promise<void>((resolve) => {
      this.categoryService
        .findAllByUser()
        .pipe(
          map((categories: any[]) => {
            const usedNames = [];
            for (const key in categories) {
              usedNames.push(categories[key].name);
            }
            return usedNames;
          })
        )
        .subscribe((categoryNames: any) => {
          this.categoryNamesInUse = categoryNames;
          resolve();
        });
    });
  }