【问题标题】:Angular Custom Async Validator stays in pending stateAngular Custom Async Validator 保持挂起状态
【发布时间】:2018-03-29 12:41:22
【问题描述】:

我有一个自定义验证器,用于验证用户的电子邮件是否唯一。

我在 stackoverflow 和互联网上搜索过相关主题,但没有任何帮助

当我在表单中提供输入(发送请求)时,请求保持在挂起状态并且不会解析。

我已经在 postman 中测试了后端,它按预期工作,问题出在客户端或角度方面。

验证函数如下:

emailUniqueValidator (control: AbstractControl): Promise<{[key: string]: any}> | Observable<{[key: string]: any}> {
    return new Promise((resolve, reject) => {
      this.userService.checkEmailUnique(control.value).subscribe((response: Response) => {
        const body = response.json();
        if (body.found === false) {
          resolve(null); // email is unique
        } else {
          reject({emailUniqueValidator: true}); // email is not unique
        }
      });
    });
  }

当我更改表单控件的值时,挂起的类会出现,但它会永远存在而不是得到解决。

我的邮件表单控件如下:

'email': new FormControl('', [
        Validators.required,
        Validators.email
      ], this.emailUniqueValidator.bind(this)
),

我的用户服务如下:

checkEmailUnique (email: string): Observable<Response> {
    return this.http.post('http://localhost:3000/user/email', {email}, { withCredentials: true });
  }

为什么验证者没有及时解决并永远处于等待状态?

编辑:

以下代码可以很好地从服务中获取价值,我已经通过将响应记录到控制台来检查它。

如果电子邮件不存在于数据库中,则解决得很好,但如果电子邮件已经存在,则会引发错误并且状态保持挂起。

return new Promise((resolve, reject) => {
      this.userService.checkEmailUnique(control.value).subscribe((response: Response) => {
        console.log(response);
        response.json().found ? reject({emailUniqueValidator: true}) : resolve(null);
      }, (error: any) => reject({emailUniqueValidator: true}));
});

【问题讨论】:

  • 有你的组件 ChangeDetectionStrategy.OnPush 吗?
  • emailUniqueValidator (control: AbstractControl): Promise&lt;{[key: string]: any}&gt; | Observable&lt;{[key: string]: any}&gt; { return this.userService.checkEmailUnique(control.value).pipe( debounceTime(500), distinctUntilChanged(), map(value =&gt; value.body.found ? {emailUniqueValidator: true} : null) ); } 这个代码对我来说很好用@Eldar

标签: angular typescript validation asynchronous


【解决方案1】:

你为什么要通过承诺来包裹可观察到的头痛?试试这样:

emailUniqueValidator (control: AbstractControl): Observable<{[key: string]: any}> {
    return this.userService.checkEmailUnique(control.value)
               .map(r => r.json())
               .map(r => (r.found) ? {emailUniqueValidator: true} : null);
 }

【讨论】:

  • 我试过你的代码,但是状态仍然是pending,你能告诉为什么会这样吗?
  • 你应该使用 do() 操作符来调试,看看是否有任何东西可以通过,这应该可以工作,有些问题在其他地方。
【解决方案2】:

observable 永远不会完成。

尝试在末尾添加.first()

emailUniqueValidator (control: AbstractControl): Observable<{[key: string]: any}> {
    return this.userService.checkEmailUnique(control.value)
               .map(r => r.json())
               .map(r => (r.found) ? {emailUniqueValidator: true} : null)
               .first();
 }

【讨论】:

  • 较新的 rxjs 版本如下所示:this.userService.checkEmailUnique(control.value).pipe(map(r =&gt; r.json()), take(1)) 省略了一些细节以保持可读性,因为代码格式化选项在 cmets 中显然是有限的。
【解决方案3】:

我遇到了同样的问题。我删除了changeDetection: ChangeDetectionStrategy.OnPush,它起作用了。一个例子is here

【讨论】:

    【解决方案4】:

    确保您的“状态代码来自”服务在任何情况下都是 200

    var user = _appRepository.GetUserByUserName(username);
    if (user != null)
    
        return Ok(user );
    }
    return Ok();
    

    这是来自 asp.net 核心 api。当用户不可用时发送空Ok()。如果角度捕获 404 或 400,则始终显示待处理。

    export function uniqueUsernameValidator(userService: UserService): AsyncValidatorFn {
      return (c: AbstractControl): Observable<{ [key: string]: any } | null> => {
        return userService.getUserByUsername(c.value).pipe(
          map(users => {
            console.log(users)
            if (users) {
              return { 'unique': true};
            }else {
              return null
            }
          })
        )
      };
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-10
      • 2019-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多