如何让我的 Searchbar 类在显示结果之前等待提取请求解决?

问题描述 投票:0回答:0

以下类监听输入元素上的“keyup”事件。然后通过

get_matches()
,它从其列表
search_terms
中找到与输入的术语匹配的所有术语。然后通过
show_matches()
,显示
autocomplete_container
中的所有匹配项。

我的问题是

search_terms
列表需要从我的服务器检索,我只想发送一个请求来这样做,而且我只想在搜索栏被使用时发送它。为了解决这个问题,我创建了一个方法
get_search_terms()
,它只在第一个“keyup”事件上触发。但这会导致一些不理想的行为,这就是我要问如何解决这个问题:

  1. 如果我的第一个输入是“a”然后我等待

    get_search_terms()
    完成,我会在方法完成后弹出自动完成列表,并显示“alice”。但是,相反,在我现在的代码中,
    get_matches()
    方法只是在
    search_terms
    列表仍然为 null 时运行,导致什么也没有发生。

  2. 我想过使用 async / await 来解决这个问题,但是,另一个问题是如果用户输入“a”,然后删除它,然后输入“b”,所有这些都是在

    search_terms
    列表被检索之前。在这种情况下,一旦列表被检索到,它将显示“alice”而不是“bob”,因为它在初始“a”输入发生后等待。

class Searchbar {
  constructor() {
  
    this.elm_form = document.querySelector(".form_search");
    this.elm_input = document.querySelector(".inp_search");
    this.elm_autocomplete_container = document.querySelector(".autocomplete_container");
    this.search_terms = null;
    this.search_terms_requested = false;
    
    this.elm_input.addEventListener("keyup", () => {
      if (!this.search_terms && !this.search_terms_requested) {
        this.search_terms_requested = true;
        this.get_search_terms();
      }
      this.show_matches(this.get_matches(this.elm_input.value));
    });
    
  }
  
  get_search_terms() {
    setTimeout(() => {
      this.search_terms = ["alice", "bob", "charlie", "dylan", "eric", "finn", "greg", "harry", "ian", "jenny", "ken", "liam", "mike", "nick", "oscar", "patrick", "quinn", "rick", "sara", "tom", "una", "victor", "wally", "xaro", "yila", "zara"];
      console.log("search terms retrieved");
    }, 2000);
  }

  get_matches(input_term) {
    if (input_term === "") return [];
    let reg = new RegExp(`^${input_term}`, "i");
    return this.search_terms?.filter((search_term) => {
      return reg.test(search_term);
    });
  }
  
  show_matches(matches) {
    if (!matches || matches.length === 0) {
    this.elm_autocomplete_container.classList.remove("shown");
    } else {
      this.elm_autocomplete_container.innerHTML = ``;
      matches.forEach(match => {
        this.elm_autocomplete_container.innerHTML += `<li>${match}</li>`;
      });
      this.elm_autocomplete_container.classList.add("shown");
    }
  }
  
}

const my_searchbar = new Searchbar();
.form_search {
  position: relative;
  width: 20rem;
}
.inp_search {
 width: 100%;
}
.autocomplete_container {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background-color: #eee;
}
.autocomplete_container.shown {
  display: block;
}
<form class="form_search">
  <input class="inp_search" type="text">
  <ul class="autocomplete_container"></ul>
</form>

javascript asynchronous
© www.soinside.com 2019 - 2024. All rights reserved.