我有一个有效的异步验证器,该验证器向服务器发出HTTP请求,以检查用户名是否已被使用。 由于我不想在每次按键后都调用API,因此需要对输入流进行去抖动。
我首先在服务中使用了<?php if(isset($errorfname)) { echo $errorfname; } ?>
,但是关于SO的另一个话题说这必须是订阅者,但是还没有运气!
我的组件:
throttleTime
我的验证者:
this.form = this._fb.group(
{
username: ['', [Validators.required, Validators.maxLength(50), NoWhitespaceValidator], [IsUserIdFreeValidator.createValidator(this._managementService)]]
});
我的服务:
export class IsUserIdFreeValidator {
static createValidator(_managementService: ManagementService) {
return (control: AbstractControl) => {
return _managementService.isUserIdFree(control.value)
.pipe(
throttleTime(5000),
(map(
(result: boolean) => result === false ? { isUserIdFree: true } : null))
);
};
}
}
答案 0 :(得分:0)
这应该可以解决问题:
static createValidator(_managementService: ManagementService) {
const subject = new BehaviorSubject('');
const observable = subject.asObservable().pipe(
debounceTime(1000),
switchMap(val => _managementService.isUserIdFree(val)),
map((isUserIdFree: boolean) => isUserIdFree ? null : { userIdTaken : true }),
);
return (control: AbstractControl) => {
subject.next(control.value);
return observable.pipe(takeUntil(timer(5000))); // acts as a way to make observable finite
}
}
反跳应该发生在控件发出的值上,而不是从http服务返回的结果上。我们首先在可观察的流上发射该值,然后将其通过distinctUntilChanged
用管道传输,这确保了与最后一个发射值相比只有唯一的值会超过管道的该阶段。 debounceTime(x)
确保仅在发出“ x”毫秒后发出最后一个值。
switchMap
运算符获取控制值,并将get请求激发到后端,然后将新的observable传递到管道的下一个阶段。最后,我将您现有的地图运算符应用于后端的结果,以生成适当的错误消息。
答案 1 :(得分:0)
我使用可观察物做到了:
form = this._fb.group({
email: [null, [Validators.required, Validators.email], [this.validateEmailNotTaken.bind(this)]]
})
private _emailCancel$ = new Subject<void>();
validateEmailNotTaken(control: AbstractControl): Observable<object> {
this._emailCancel$.next();
return race(
timer(3000).pipe(map(_ => true)),
this._emailCancel$.pipe(
map(_ => false)
)
).pipe(
take(1),
filter(val => !!val),
switchMap(() => this.isEmailTaken(control.value).pipe(
map(res => res ? {isTaken: true } : null)
))
);
}
答案 2 :(得分:0)
对于任何发现此问题和答案的人,恕我直言,该问题是this one的重复。我认为这个answer是正确的,除非您喜欢Promises。我打算在那里发布采用最新版本(Angular 9+)解决方案的答案。
编辑:here's my suggestion了解操作方法。
顺便说一句,在遇到这个问题和另一个问题之前,我尝试了此处列出的所有三个答案。您可以使它们全部起作用,但是我链接的答案无疑是最优雅的。很难弄清楚,因为它依赖于Angular框架中应该真正包含在文档中的行为。
答案 3 :(得分:-1)