有一个搜索功能,用户可以在表单中输入多个搜索条件,然后单击搜索按钮,搜索操作开始。
此搜索条件表单中很少有下拉字段。在下拉列表中选择一个值会触发 API 调用以获取特定 ID,该 ID 将在请求负载的查询中传递以获取搜索结果。
API调用是通过一定的方法进行的,搜索点击是单独的方法。 结构如下所示 -
/**
* Method to capture changes in the form
*/
valueChanges(control, change) {
if (control === TYPE1) {
// update the search query
} else if (control === TYPE2) {
// get the ID by making API call
this.getID()
}
}
/**
* Method to get certain ID
*/
private getId() {
this.http.get(url, params).subscribe(res => {
const formValue = this.reactiveForm.value
// id fetched and saved to form value
formValue['id'] = res.content.id
// update the search query
})
}
/**
* Method to start search operation by making another API call
*/
public performSearch() {
this.http.post(url, params).subscribe(res => {
// get search results
})
}
当用户在选择触发 API 调用的下拉值后立即单击“搜索”按钮时,就会出现问题。这样的话,获取ID的API还没有结束,search()方法会执行。
如何避免这种情况?
P.S. 禁用该按钮是我的最后一个选择。我在这里寻找一些更好的选择。
您可以添加一个标志变量来保存
getId
方法的状态,并等待它完成。
您可以使用
BehaviorSubject
,并从 getId
方法切换状态,然后在搜索按钮单击事件上的新 prepareSearch
方法中订阅它,并使用 takeWhile
阻止处理,直到完成。
尝试一下,
isApiLoading$
的初始值设置为false
,表示它没有执行请求,当执行时,它会从true
方法将值更改为getId
,直到请求完成,然后将其设置回 false
。
当点击按钮时,
prepareSearch
方法将获取最新值,如果为假,则执行请求,否则等待getId
完成:
private isApiLoading$ = new BehaviorSubject<boolean>(false);
/**
* perform search only when getId is done
*/
public prepareSearch() {
this.isApiLoading$
.pipe(
// block pefrom search until getId() is done
takeWhile((val) => !!val)
)
.subscribe(
(val) => console.log(val),
(err) => console.log(err),
// getId() done or not performing, now call performSearch()
() => this.performSearch()
);
}
/**
* Method to get certain ID
*/
private getId() {
// block peform search
this.isApiLoading$.next(true);
this.http.get(url, params).subscribe(res => {
const formValue = this.reactiveForm.value
// id fetched and saved to form value
formValue['id'] = res.content.id
// update the search query
// unblock perform search
this.isApiLoading$.next(false);
})
}