Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/460.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在异步验证器中使用debounceTime()和distinctUntilChanged()_Javascript_Angular_Typescript_Angular Forms - Fatal编程技术网

Javascript 如何在异步验证器中使用debounceTime()和distinctUntilChanged()

Javascript 如何在异步验证器中使用debounceTime()和distinctUntilChanged(),javascript,angular,typescript,angular-forms,Javascript,Angular,Typescript,Angular Forms,我想在我的异步验证器中添加debounceTime和distinctUntilChanged mockAsyncValidator():AsyncValidator fn{ 返回(控件:FormControl):可观察=>{ 返回控制.valueChanges.pipe( 去BounceTime(500), distinctUntilChanged(), 开关映射(值=>{ console.log(value);//log在这里工作 返回此.mockService.checkValue(valu

我想在我的异步验证器中添加
debounceTime
distinctUntilChanged

mockAsyncValidator():AsyncValidator fn{
返回(控件:FormControl):可观察=>{
返回控制.valueChanges.pipe(
去BounceTime(500),
distinctUntilChanged(),
开关映射(值=>{
console.log(value);//log在这里工作
返回此.mockService.checkValue(value).pipe(响应=>{
console.log(response);//这里的日志不起作用
如果(答复){
返回{invalid:true};
}
返回null;
})
})
);
}
上面的代码不起作用,表单状态变为
PENDING

但是当我在中使用
timer
时,代码可以工作,但是我不能使用
distinctunitrichanged

返回计时器(500)。管道(
开关映射(()=>{
返回此.mockService.checkValue(control.value).pipe(响应=>{
console.log(response);//日志在这里工作
如果(答复){
返回{invalid:true};
}
返回null;
})
})
);
我试着像这样使用
行为主体

debouncedSubject=新行为主体(“”);
并在
异步验证程序fn
中使用它,但仍然不起作用,如下所示:

this.debouncedSubject.next(control.value);
返回此.debouncedSubject.pipe(
去BounceTime(500),
distinctUntilChanged(),//不起作用
//我想可能是因为我知道这个值
//就在上面
//但我不知道如何解决这个问题
假设(1),//必须添加此项,否则表单将永远挂起
//这个take(1)不能在debounceTime()之前添加
//否则,debounceTime()将无法工作
开关映射(值=>{
console.log(value);//log在这里工作
返回此.mockService.checkValue(control.value).pipe(响应=>{
console.log(response);//日志在这里工作
如果(答复){
返回{invalid:true};
}
返回null;
}
);
})
);

问题在于每次调用
pipe()时执行验证器fn时都会生成一个新管道
在验证器fn内部。先前的值不是为discinct或debounce工作而捕获的。在我的情况下,您可以在外部设置两个
行为主题
术语Debouncer
ValidationCommitter

您可以设置一个工厂方法来创建此验证器,从而重新使用它。您还可以扩展
AsyncValidator
,并使用DI设置创建一个类。我将在下面展示工厂方法

export function AsyncValidatorFactory(mockService: MockService) { 
  const termDebouncer = new BehaviorSubject('');
  const validationEmitter = new BehaviorSubject<T>(null);
  let prevTerm = '';
  let prevValidity = null;

  termDebouncer.pipe(
        map(val => (val + '').trim()),
        filter(val => val.length > 0),
        debounceTime(500),
        mergeMap(term => { const obs = term === prevTerm ? of(prevValidity) : mockService.checkValue(term);
          prevTerm = term; 
          return obs; }),
        map(respose => { invalid: true } : null),
        tap(validity => prevValidity = validity)
    ).subscribe(validity => validationEmitter.next(validity))


  return (control: AbstractControl) => {
    termDebouncer.next(control.value)
    return validationEmitter.asObservable().pipe(take(2))
  }
}

导出函数AsyncValidatorFactory(mockService:mockService){
const termDebouncer=新行为主体(“”);
const validationEmitter=新行为主体(null);
让prevTerm='';
设prevValidity=null;
termDebouncer.pipe(
映射(val=>(val+'.trim()),
过滤器(val=>val.length>0),
去BounceTime(500),
mergeMap(term=>{const obs=term===prevTerm?of(prevValidity):mockService.checkValue(term);
prevTerm=期限;
返回obs;}),
映射(respose=>{invalid:true}:null),
点击(有效期=>prevValidity=有效期)
).subscribe(有效性=>validationMitter.next(有效性))
返回(控件:AbstractControl)=>{
termDebouncer.next(control.value)
返回validationMitter.asObservable()管道(取(2))
}
}
编辑:此代码摘录自除角度形式验证之外的用例(精确地说,是React search widget)。管道操作符可能需要更改以适合您的用例

Edit2
take(1)
first()
管道操作符将异步管道分支,并从此处开始创建新的可观察对象。您可能必须使用
take(2)
来克服行为主体是有状态的并持有值这一事实


Edit3:使用合并映射来处理事实
distinctUntilChanged()
将导致可观察对象不发出且不完整。

我认为
debounceTime()
应该在
distinctUntilChanged()之前调用
。由于
termdbouncer
中的
val
的类型是
string
,因此您似乎可以在第一个
映射()中直接使用
val.trim()
。这是从我的一个项目中摘录的,其中的值可以是
数字
字符串
。我复制、粘贴了一些,并添加了一些。是的,你在
distinctUntilChanged()
上是正确的。我发现尽管
debounceTime()
distinctUntilChanged())
现在可以正常工作了,它会使表单卡在
挂起
状态。
take(1)
first()
似乎不是解决此问题的正确方法,因为它们中的任何一个都将“完成”Observable()语句将在每次验证输入时被调用,您可以通过管道将其传递到那里。您是对的,我错误地将
将管道连接到
终端公告器上
。现在异步验证可以完成。但另一个进退两难的情况出现了:如果
distinctUntilChanged()
失败,
mockService
将不会执行,因此不会向
validationEmitter
发送任何消息,并再次以
PENDING
状态形成stuck。它