非同步驗證器(Async Validator)
非同步驗證器同樣接收表單控制項(control)作為參數,但必須返回一個 Observable。這讓我們可以執行非同步操作,例如發送 HTTP 請求到後端驗證資料。
基本結構
typescriptCopyimport { AbstractControl, AsyncValidatorFn, ValidationErrors } from '@angular/forms';
import { Observable, of } from 'rxjs';
function emailIsUnique(control: AbstractControl): Observable<ValidationErrors | null> {
if (control.value !== 'test@test.com') {
// 這裡只是模擬,實際使用時會呼叫 API
return of(null); // 驗證通過
}
return of({ notUnique: true }); // 驗證失敗
}
使用方式:
typescriptCopyemail: new FormControl('', {
validators: [Validators.required, Validators.email],
asyncValidators: [emailIsUnique],
}),

重要特性
觸發時機:非同步驗證器只有在所有同步驗證器都通過後才會被觸發,這樣可以避免不必要的 API 調用。
Pending 狀態:當非同步驗證進行時,表單控制項會進入 "pending" 狀態,可以用來顯示載入指示器:
htmlCopy@if(loginForm.controls.email.pending){ <p>Checking email...</p> }
實際 HTTP 請求:在實際應用中,通常會使用服務來發送 HTTP 請求:
typescriptCopy// 簡化的示例 function emailIsUnique(userService: UserService): AsyncValidatorFn { return (control: AbstractControl): Observable<ValidationErrors | null> => { return userService.checkEmailExists(control.value).pipe( map(exists => exists ? { notUnique: true } : null) ); }; }
防抖處理:為避免每次按鍵都發送請求,通常會添加防抖:
typescriptCopy// 加入防抖處理的概念性示範 import { debounceTime, switchMap } from 'rxjs/operators'; return of(control.value).pipe( debounceTime(500), // 500ms 防抖 switchMap(value => userService.checkEmailExists(value)) );
非同步驗證器非常適合用於檢查值的唯一性,例如驗證使用者名稱或電子郵件是否已被使用。在表單提交前,所有的非同步驗證器都必須完成並通過,表單才會被視為有效。
Last updated