如何在对用户输入进行异步调用时过滤项目?
How to filter items while doing async calls on user input?
我的 HTML 中有一个输入字段,如下所示:
<input (keyup)="userInput($event)" type="text">
在我的组件中,我接受用户输入并检查后端是否是有效输入。在进行此调用之前,我对变量进行了简单的空检查。
userInput(e: any): void {
this.userInputText = e.target.value;
if (this.userInputText === '') { //Empty string check
this.validInput = false;
} else { // Check backend for availability
this.userInput.next(this.userInputText);
}
}
我的用户输入主题是
this.userInput
.debounceTime(1000)
.switchMap((val) => {
return this.checkValidity(val); //service call
}).subscribe((res) => {
this.validInput = res.status;
}, (err) => {
ResponseHandler(err);
});
问题是我做的空头支票。
假设用户输入了两个字符 'of',我将其显示为有效(通过调用)。
如果用户按下退格键(输入现在是 'o'),等待一秒钟(导致调用文本 'o')然后按下退格键删除 'o'(导致空的用户输入)我的状态显示无效,因为输入字段为空。
然后 ajax 呼叫响应返回(对于文本 'o',这是有效的)并且我显示有效。所以我最终显示对空字符串有效。
我该如何解决这个问题?有什么想法吗?
问题是您正在执行异步操作并期望同步结果。您需要找到一种方法来解决程序的异步性质。
立即想到的一些可能的解决方案:
1) 您可以在进行服务器端验证时禁用输入。
2) 由于解决方案 1 不太流畅,您可以考虑在将请求发送到服务器之前设置一个标志(例如 input_changed_during request = false;
,在输入更改时修改其值(例如 input_changed_during_request = true;
,然后在收到来自服务器的状态后检查它,如果输入在验证过程中被修改,则丢弃您的验证结果。
3) 您可以在客户端执行去抖动输入验证,然后在提交时到达服务器时重新验证输入。
您只需要将空支票放入可观察流中,而无需进行其他工作...
this.userInput
.debounceTime(1000)
.distinctUntilChanged()
.switchMap((val) => (val) ? this.checkValidity(val) : Observable.of({status: false}))
.subscribe((res) => {
this.validInput = res.status;
}, (err) => {
ResponseHandler(err);
});
然后直接将密钥绑定到用户输入主题
由于 switchmap 运算符的工作方式,这解决了您的计时问题。
switchMap 获取一个值并将其映射到对新内部可观察对象的订阅,但更重要的是,它取消并忽略了之前订阅的内部可观察对象的值。这就是为什么对于 switch map,如果用户输入 w 然后 o,switch map 收到 "w" 然后 "wo" 并不重要,因为一旦它获得第二个值,异步 "w" 查询是否有 returned,或者如果 "wo" 查询(以某种方式)击败了 "w" 查询,因为它将忽略或取消 "w" 查询一旦它收到新的 "wo" 值,空白值也是如此,就好像用户在之前的查询完成之前删除了他们的输入一样,switchMap 将忽略或取消所有之前未完成的查询,并且它将仅 return 来自最新内部可观察对象的模拟无效查询结果。这就是它被称为 switchMap 的原因,它切换并映射到最新的内部可观察对象。
如果你要使用像 mergeMap 这样的运算符,它是一个不同的高阶运算符,它也映射到一个新的内部可观察对象,这个过程将不起作用,因为 mergeMap 不会切换,它 returns 所有来自内部可观察值的值按它们到达的顺序排列,不管新值进来什么。有时这就是你所追求的,但在这种情况下不是。
额外提示,我添加的 distinctUntilChanged() 运算符使此过程更加高效,就好像用户要执行类似输入 w(执行查询)然后输入 o 并立即删除debounce 时间帧,它将忽略下一个发送的 "w",因为它只将新值传递给 switchmap 并忽略顺序重复值,因此您不必重新查询 "w"
我的 HTML 中有一个输入字段,如下所示:
<input (keyup)="userInput($event)" type="text">
在我的组件中,我接受用户输入并检查后端是否是有效输入。在进行此调用之前,我对变量进行了简单的空检查。
userInput(e: any): void {
this.userInputText = e.target.value;
if (this.userInputText === '') { //Empty string check
this.validInput = false;
} else { // Check backend for availability
this.userInput.next(this.userInputText);
}
}
我的用户输入主题是
this.userInput
.debounceTime(1000)
.switchMap((val) => {
return this.checkValidity(val); //service call
}).subscribe((res) => {
this.validInput = res.status;
}, (err) => {
ResponseHandler(err);
});
问题是我做的空头支票。
假设用户输入了两个字符 'of',我将其显示为有效(通过调用)。
如果用户按下退格键(输入现在是 'o'),等待一秒钟(导致调用文本 'o')然后按下退格键删除 'o'(导致空的用户输入)我的状态显示无效,因为输入字段为空。
然后 ajax 呼叫响应返回(对于文本 'o',这是有效的)并且我显示有效。所以我最终显示对空字符串有效。 我该如何解决这个问题?有什么想法吗?
问题是您正在执行异步操作并期望同步结果。您需要找到一种方法来解决程序的异步性质。
立即想到的一些可能的解决方案:
1) 您可以在进行服务器端验证时禁用输入。
2) 由于解决方案 1 不太流畅,您可以考虑在将请求发送到服务器之前设置一个标志(例如 input_changed_during request = false;
,在输入更改时修改其值(例如 input_changed_during_request = true;
,然后在收到来自服务器的状态后检查它,如果输入在验证过程中被修改,则丢弃您的验证结果。
3) 您可以在客户端执行去抖动输入验证,然后在提交时到达服务器时重新验证输入。
您只需要将空支票放入可观察流中,而无需进行其他工作...
this.userInput
.debounceTime(1000)
.distinctUntilChanged()
.switchMap((val) => (val) ? this.checkValidity(val) : Observable.of({status: false}))
.subscribe((res) => {
this.validInput = res.status;
}, (err) => {
ResponseHandler(err);
});
然后直接将密钥绑定到用户输入主题
由于 switchmap 运算符的工作方式,这解决了您的计时问题。
switchMap 获取一个值并将其映射到对新内部可观察对象的订阅,但更重要的是,它取消并忽略了之前订阅的内部可观察对象的值。这就是为什么对于 switch map,如果用户输入 w 然后 o,switch map 收到 "w" 然后 "wo" 并不重要,因为一旦它获得第二个值,异步 "w" 查询是否有 returned,或者如果 "wo" 查询(以某种方式)击败了 "w" 查询,因为它将忽略或取消 "w" 查询一旦它收到新的 "wo" 值,空白值也是如此,就好像用户在之前的查询完成之前删除了他们的输入一样,switchMap 将忽略或取消所有之前未完成的查询,并且它将仅 return 来自最新内部可观察对象的模拟无效查询结果。这就是它被称为 switchMap 的原因,它切换并映射到最新的内部可观察对象。
如果你要使用像 mergeMap 这样的运算符,它是一个不同的高阶运算符,它也映射到一个新的内部可观察对象,这个过程将不起作用,因为 mergeMap 不会切换,它 returns 所有来自内部可观察值的值按它们到达的顺序排列,不管新值进来什么。有时这就是你所追求的,但在这种情况下不是。
额外提示,我添加的 distinctUntilChanged() 运算符使此过程更加高效,就好像用户要执行类似输入 w(执行查询)然后输入 o 并立即删除debounce 时间帧,它将忽略下一个发送的 "w",因为它只将新值传递给 switchmap 并忽略顺序重复值,因此您不必重新查询 "w"