Angular 7:为什么我必须两次调用我的订阅方法才能生效

问题描述 投票:-3回答:2

我认为我误解了Subscriptions和Observables,我发现Angular文档并没有特别有用。

我正在创建一个验证服务,用于检查用户名是否可用。在表单提交时调用validationService,如果用户名不可用,将显示错误消息。问题是,我必须提交两次表格才能使用。

validationService对后端进行http调用,返回一个布尔值。我有一个局部变量'availableUsername',我想将结果设置为,以便我可以在其他地方使用它。在subscribe函数内部工作正常,我得到结果并将其设置为此变量。但是当我离开subscribe方法的范围时,变量是未定义的。但是,当我再次呼叫提交时,它会起作用。

我在下面添加了validationService和userService。

validationService.ts

import { Injectable } from '@angular/core';
import { FormControl } from '@angular/forms';

import { AlertService } from './../services/alert.service';
import { UserService } from './../services/user.service';

@Injectable({
  providedIn: 'root'
})
export class ValidationService {

  availableUsername: boolean;
  availableEmail: boolean;

  constructor(
    private alertService: AlertService,
    private userService: UserService
    ) { }

  validateUsername(controls: any): boolean {

    const username = controls.username.value;

    this.isUsernameAvailable(username);

    if (!this.availableUsername) {
      this.alertService.error('This username is already taken', false);
      return true;
    }
    return false;
  }

  private isUsernameAvailable(username: string) {

    if (username === undefined || username === '') {
      return;
    }

    this.userService.isUserNameAvailable(username)
      .subscribe((result) => {
        this.availableUsername = result;
    },
    error => {
      this.alertService.error(error);
      return;
    });
  }

}

userService.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { environment } from './../../environments/environment';

@Injectable({ providedIn: 'root' })
export class UserService {

  apiUrl: string = environment.apiUrl;

  constructor(private http: HttpClient) { }

  isUserNameAvailable(username: string) {
    return this.http.get<boolean>(`${this.apiUrl}/users/checkUsernameAvailability/${username}`);
  }

}
angular scope rxjs angular2-observables subscribe
2个回答
0
投票
this.isUsernameAvailable(username); 

当执行上面这行代码时,它将异步运行,所以在通过订阅为qazxsw poi赋值之前,下面的代码将运行

this.availableUsername = result;

要避免这样做,请在订阅中检查此条件,如下所示

 if (!this.availableUsername) {
      this.alertService.error('This username is already taken', false);
      return true;
    }
    return false;
  }

-1
投票

您的代码中的问题是您尝试同步使用异步流, this.userService.isUserNameAvailable(username) .subscribe((result) => { this.availableUsername = result; }, error => { this.alertService.error(error); return; } ()=>{ if (!this.availableUsername) { this.alertService.error('This username is already taken', false); } } ); } } 属性值将仅在调用availableUsername回调时设置,这将在subscribe之后很长时间。

在这种情况下,您可以使用为这些情况构建的if (!this.availableUsername)

另一个(不太推荐)替代方案是使您的代码同步运行使用asyncValidartorasync

© www.soinside.com 2019 - 2024. All rights reserved.