(角度 12)仅当执行具有 http 调用的方法时,按钮单击才应继续

(Angular 12) Button click should proceed only if a method having http call is done executing

提问人:Pranjal Successena 提问时间:8/19/2023 更新时间:8/20/2023 访问量:86

问:

有一个搜索功能,用户可以在表单中输入多个搜索条件,单击搜索按钮后,搜索操作开始。

在此搜索条件表单中,很少有字段是下拉列表。在下拉列表中选择一个值会触发 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() 方法执行。

如何避免这种情况?

附言禁用按钮是我的最后一个选择。我在这里寻找一些更好的选择。

角度 异步 搜索

评论


答:

1赞 traynor 8/20/2023 #1

您可以添加一个标志变量,该变量将保存方法的状态,并等待它完成。getId

你可以使用 ,并从方法中切换状态,然后在搜索按钮点击事件的新方法中订阅它,并使用 创建阻塞处理效果,直到完成。BehaviorSubjectgetIdprepareSearchtakeWhile

尝试此操作,将初始值设置为 ,以指示它没有执行请求,当它执行时,它会将值更改为 from 方法,直到请求完成,然后将其设置回 。isApiLoading$falsetruegetIdfalse

当按钮被点击时,method 将获取最新的值,如果为 false,它将执行请求,否则它将等待完成:prepareSearchgetId

private isApiLoading$ = new BehaviorSubject<boolean>(false);

/**
 * perform search only when getId is done
 */
public prepareSearch() {
    
    this.isApiLoading$
      .pipe(
        // do not perform 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);

    })
}