Angular 7:为什么我必须调用我的subscribe方法两次才能生效
我认为我误解了订阅和观测,我不觉得角度文档特别有用 我正在创建一个validationService,用于检查用户名是否可用。表单提交时调用validationService,如果用户名不可用,则会显示错误消息。问题是,我必须提交两次表格才能生效 validationService对后端进行http调用,返回布尔值。我有一个局部变量“availableUsername”,我想将结果设置为,以便在其他地方使用它。在subscribe函数中,它工作正常,我得到结果并将其设置为这个变量。但是当我离开subscribe方法的作用域时,变量是未定义的。但当我再次调用submit时,它就起作用了 我在下面添加了validationService和userService validationService.tsAngular 7:为什么我必须调用我的subscribe方法两次才能生效,angular,scope,rxjs,angular2-observables,subscribe,Angular,Scope,Rxjs,Angular2 Observables,Subscribe,我认为我误解了订阅和观测,我不觉得角度文档特别有用 我正在创建一个validationService,用于检查用户名是否可用。表单提交时调用validationService,如果用户名不可用,则会显示错误消息。问题是,我必须提交两次表格才能生效 validationService对后端进行http调用,返回布尔值。我有一个局部变量“availableUsername”,我想将结果设置为,以便在其他地方使用它。在subscribe函数中,它工作正常,我得到结果并将其设置为这个变量。但是当我离开s
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;
});
}
}
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}`);
}
}
userService.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;
});
}
}
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/core'导入{Injectable};
从'@angular/common/http'导入{HttpClient};
从“/../../environments/environment”导入{environment};
@可注射({providedIn:'root'})
导出类用户服务{
apiUrl:string=environment.apiUrl;
构造函数(私有http:HttpClient){}
IsUserName可用(用户名:字符串){
返回this.http.get(`${this.apirl}/users/checkUsernameAvailability/${username}`);
}
}
代码中的问题是您试图使用异步流同步
只有在调用subscribe
回调时,才会设置availableUsername
属性值,这将在if(!this.availableUsername)
之后很久
在这种情况下,您可以使用为这些情况构建的
另一种(不太推荐的)替代方法是使用async
和wait
同步运行代码
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);
}
}
);
}
}
AJAX中的A表示异步。传递给subscribe()的函数初始化this.availableUsername
,在验证器返回其结果后立即执行。您需要使用异步验证器。但最重要的是,您需要了解异步的原理。所以validateUsername不是在等待IsUserName完成吗?是的,它是在等待。正如您所看到的,isUsername不会返回任何内容。它所做的只是发送一个http请求并立即返回。此时,isUsernameAvailable()已完成。但是,对请求的响应将在很久以后由回调处理。就像,如果我告诉你“请为我烤一片面包”,你将在2秒钟内完成这项任务:将面包放入烤面包机所需的时间。不过,我要等很久才能吃到吐司:当烤面包机响起来通知我吐司准备好了。当烤面包机慢慢地烤面包的时候,你和我做了很多其他的事情。