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

时间:2019-03-23 12:44:01

标签: angular scope rxjs angular2-observables subscribe

我需要一些帮助。我认为我误解了Subscriptions and Observables,但我发现Angular文档没有特别的帮助。

我正在创建用来检查用户名是否可用的validationService。 ValidationService在表单提交时调用,如果用户名不可用,则会显示一条错误消息。问题是,我必须提交两次表单才能使其正常工作。

validationService对后端进行http调用,返回一个布尔值。我有一个本地变量“ availableUsername”,我要将结果设置为该变量,以便可以在其他地方使用它。在订阅函数内部,它工作正常,我得到了结果并将其设置为该变量。但是当我离开订阅方法的范围时,该变量未定义。但是,当我再次调用Submit时,它可以工作。

我在下面添加了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}`);
  }

}

2 个答案:

答案 0 :(得分:0)

this.isUsernameAvailable(username); 

在执行完以上代码后,它将异步运行,因此在为this.availableUsername = result;赋值之前 通过订阅,以下代码将运行

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

要避免发生这种情况,请检查订阅中的这种情况

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

    }
}
);
      }

    }

答案 1 :(得分:-1)

代码中的问题是您尝试异步同步 availableUsername属性值仅在调用subscribe之后才设置,该调用将在if (!this.availableUsername)之后很长时间。

在这种情况下,您可以使用为这些情况构建的asyncValidartor

另一种(不建议使用的方法)是使代码使用asyncawait同步运行。