我认为我误解了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}`);
}
}
this.isUsernameAvailable(username);
当执行上面这行代码时,它将异步运行,所以在通过订阅为qazxsw poi赋值之前,下面的代码将运行
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);
}
}
);
}
}
属性值将仅在调用availableUsername
回调时设置,这将在subscribe
之后很长时间。
在这种情况下,您可以使用为这些情况构建的if (!this.availableUsername)
。
另一个(不太推荐)替代方案是使您的代码同步运行使用asyncValidartor和async
。