자동 완성기 구축

AutoCompleter 구축은 일반적으로 여러 하위 작업과 함께 제공되는 또 다른 일반적인 인터뷰 질문입니다.

처음부터 바닐라 js로 자동 완성기를 구축하는 작업은 다음과 같이 나눌 수 있습니다.
  • 검색 기능
  • 모의 API
  • 지연된 응답 처리
  • 디바운스

  • 먼저 모의 API를 설정합니다.

    // generate random response string
    const randomStr = () => Math.random().toString(36).substring(2, 8);
    
    // generate a random value within a range
    // for varying response delays
    const randomInRange = (min = 0, max = 5) =>
      min + Math.floor(Math.random() * max);
    
    const mockApi = (searchText, delay = 1000 * randomInRange(0, 3)) => {
      const results = [];
    
      if (searchText === "") {
        return Promise.resolve(results);
      }
    
      for (let i = 0; i < randomInRange(3, 5); i++) {
        results.push(`${searchText} - ${randomStr()}`);
      }
    
      return new Promise((resolve, reject) => {
        window.setTimeout(() => {
          randomInRange(0, 25) === 24
            ? reject("Internal server error")
            : resolve(results);
        }, delay);
      });
    };
    


    HTML 부분

          <div>
            <input id="searchbox" />
            <div id="resultbox" />
          </div>
    


    AutoCompleter는 수신할 입력 필드와 결과를 전달하기 위한 콜백의 두 가지 매개변수를 허용합니다.

    mockApi를 호출하는 keyup 이벤트를 추가하고 결과를 기다리며 완료되면 결과와 함께 콜백 함수를 호출합니다.

    한 가지 일반적인 시나리오는 순서가 잘못된 응답을 처리하는 것입니다. search#1은 3초 후에 돌아왔고 search#2는 1초 이내에 응답했을 수 있습니다. 이를 위해 클로저를 사용하여 최신 쿼리를 추적하거나 콜백을 실행하기 전에 검색 필드의 텍스트를 확인해야 합니다.

    function AutoCompleter(searchBox, doneCallback) {
      let latestQuery = "";
    
      // search action
      async function triggerSearch(event) {
        try {
          const text = event.target.value;
          latestQuery = text; // keep track of latest search text
          const result = await mockApi(text);
          // handle delays
          if (latestQuery === text) {
            doneCallback(result);
          }
        } catch (err) {
          console.log("api error");
        }
      }
    
      // add event listener
      searchBox.addEventListener("keyup", triggerSearch);
    
      // way to remove the listener
      return {
        clear: () => {
          searchBox.removeEventListener("keyup", triggerSearch);
        }
      };
    }
    


    키를 누를 때마다 검색을 트리거하면 원치 않는 호출이 여러 번 발생할 수 있으므로 사용자가 입력을 일시 중지할 때만 검색을 트리거하는 것이 좋습니다. 디바운싱 및 조절에 대해 자세히 알아보기here

    function debouce(fn, delay=250) {
      let timeoutId = null;
      return (...args) => {
        if (timeoutId) {
          clearTimeout(timeoutId);
        }
        timeoutId = setTimeout(() => {
          fn(...args);
        }, delay);
      };
    }
    


    검색을 위해 디바운스된 기능 사용

     const debouncedSearch = debouce(triggerSearch, 250);
    
     // add event listener
     searchBox.addEventListener("keyup", debouncedSearch);
    


    자동 완성기 호출

    const searchInstance = new AutoCompleter(document.getElementById("searchbox"), (output) => {
      document.getElementById("resultbox").innerText = output;
    });
    
    // searchInstance.clear();
    


    최신 쿼리를 확인하면 응답이 지연되는 문제가 해결되지만 주요 문제에 대한 가능한 추가 질문은 최신 약속을 얻는 문제에 대한 일반적인 솔루션을 구현하는 것입니다.

    function latestPromise(fn) {
      let latest = null;
    
      return (...args) => {
        latest = fn(...args); // update the latest promise
        return new Promise(async (resolve, reject) => {
          const current = latest;
          try {
            const res = await current;
            // check before resolving
            current === latest ? resolve(res) : console.log("skip");
          } catch (err) {
            reject(err);
          }
        });
      };
    }
    


    몇 가지 빠른 테스트

    const wrappedMockApi = latestPromise(mockApi);
    
    async function searchAction(text, delay) {
      const res = await wrappedMockApi(text, delay);
      console.log("res", res);
    }
    
     searchAction("search-1", 1000);
     searchAction("search-2", 400);
     searchAction("search-3", 200);
     searchAction("search-4", 100);
     // response log will show value only for search-4
     // reminaining will be skipped
    
    


    대부분의 경우 모의 API와 HTML은 상용구의 일부가 되며 나머지 코드를 작성하는 데 약 40분이 소요됩니다.

    작업 코드를 볼 수 있습니다 here

    좋은 웹페이지 즐겨찾기