サーバー負荷が少ないインクリメンタルサーチの作り方

キーワード検索するとき、検索ボタンを押さなくとも、入力された時点で自動的に検索結果が表示されるインクリメンタルサーチは今や多くのWebサイトで利用されています。

インクリメンタルサーチを実装するにはいくつかの方法がありますが、changeイベントは一度フォーカスをはずさないと発火しないので、keyupでやることが多いと思います。

しかしながらこの実装方法では、入力キーが押される度、通信が走るため、必要以上にサーバーに負荷をかけてしまいます。

今回は必要以上にイベントを発火させない方法について解説します。

対処法

ここではjQueryを使った例を扱いますが、axiosなどを使ったときも同様の処理が可能です。

HTMLは次のようなものを想定しています。

<input id="keyword" data-href="/your/search/path"/>
<ul id="result-list">
  <!-- ここに結果が反映される。 -->
</ul>

ここで、inputタグ内のdata-hrefは検索結果を返すエンドポイントのURLを記述します。

さて、本題のサーバーの負荷を減らすために「キーをタイプした後、しばらく入力がなければ、Ajaxを投げる」という発想でJSを記述します。

$(function(){
  var $keyword = $('#keyword');
  var $resultList = $('#result-list');
  var url = $keyword.data('href');
  // Ajax通信を行う関数
  function send(){
    $.ajax({
      type: 'GET',
      dataType: 'html',
      data: {
        keyword: $keyword.val(),
        url: url,
        success: function(data){
          // 通信が成功したらリストを総入れ替え
          $resultList.html(data)
        }
      }
    });
  };
  var send_timeout_id = null
  $keyword.on('keyup', function(){
    // keyupされた時点で既にsendの実行が予約されていたら一旦削除
    if(send_timeout_id){
      clearTimeout(send_timeout_id);
    }
    // 500ms後にsendを実行するように予約
    send_timeout_id = setTimeout(send, 500);
  }
});

まとめ

Ajaxを使うとUX的にはいいものにすることが可能ですが、上手くやらないとサーバーへの無駄な負荷をかけてしまい、表示が遅くなるなど、ユーザーのストレスにつながりかねません。

いつ、どのくらいの頻度で通信が行われるのかしっかり意識しながら、ユーザーが気持ちよく使えるシステムを作っていきましょう!