2020.1.23

テキストボックスの内容が変わる度に検索を行う処理の負荷軽減

画面上のテキストボックスに文字を入力したタイミングで検索処理を実行する場合、1文字を入力する度に検索をかけると検索対象のデータの量や処理によっては重たくなるので、これを改善する方法のメモです。

データバインドや画面への変更が面倒だったので、サンプルはvue.jsを使用してます。vue.jsを使わない場合は、適宜、読み替えてください。

目次

  • 通常の検索処理
  • 変更後の検索処理(負荷軽減処理を入れた検索)
  • 検索方法の違いについて

通常の検索処理

検索用のテキストボックスの値が入力される度に検索処理が発生するは以下の通り。(検索対象となるデータは分かりやすいように件数を多くしています)


<h3>通常の検索処理</h3>
<div id="app">
  <input v-model="searchWord" v-on:keyup="changeSearchWord">
  <ol>
    <li v-for="todo in searchedTodos">
      {{ todo.text }}
    </li>
  </ol>
</div>

<script>
var app = new Vue({
  el: '#app',
  data: {
    searchWord: "",
    searchedTodos: [],
    todos:[]
  },
  mounted:function () {
    var arr = new Array("aaa","aaabbb","aaabbbccc","aaabbbcccddd","aaabbbcccdddeee");
    for(var i = 1; i <= 20000; i++){
      this.todos.push({id:i, text : arr[i % arr.length] + i});
    }
    this.search();
  },
  methods: {
    changeSearchWord: function (event) {
      this.search();
    },
    search: function(){
      this.searchedTodos = [];
      this.todos.forEach(todo => {
        if(this.searchWord == "" || todo.text.indexOf(this.searchWord) != -1){
          this.searchedTodos.push(todo);
        }
      });
    }
  }
});
</script>

動作確認はこちら

変更後の検索処理(負荷軽減処理を入れた検索)

上記の検索処理では、データ数が少なければそこまで問題ありませんが、データ数が多くなると、検索に時間がかかるため、入力した内容がなかなか検索用のテキストボックスに反映されなくなります。

上記の状態を改善したのが以下の処理。


<h3>変更後(負荷軽減)の検索処理</h3>
<div id="app">
  <input v-model="searchWord" v-on:keyup="changeSearchWord">
  <ol>
    <li v-for="todo in searchedTodos">
      {{ todo.text }}
    </li>
  </ol>
</div>

<script>
var app = new Vue({
  el: '#app',
  data: {
    searchWord: "",
    searchedTodos: [],
    todos:[]
  },
  mounted:function () {
    var arr = new Array("aaa","aaabbb","aaabbbccc","aaabbbcccddd","aaabbbcccdddeee");
    for(var i = 1; i <= 20000; i++){
      this.todos.push({id:i, text : arr[i % arr.length] + i});
    }
    this.search();
  },
  methods: {
    changeSearchWord: function (e) {
      var searchWordBefore = this.searchWord;
      setTimeout(function(){
        if(searchWordBefore == this.searchWord){
          this.search();
        }
      }.bind(this),300)
    },
    search: function(){
      this.searchedTodos = [];
      this.todos.forEach(todo => {
        if(this.searchWord == "" || todo.text.indexOf(this.searchWord) != -1){
          this.searchedTodos.push(todo);
        }
      });
    }
  }
});
</script>

動作確認はこちら

検索方法の違いについて

改善した処理の変更点はメソッド「changeSearchWord」内の処理でsetTimeoutを呼び出し、一定時間(300ms)経過後に、検索用テキストボックスの内容が変わっていなければ検索処理を実行するようにしています。

即座に反映はされなくなりますが、検索対象のデータ数が多い場合はこちらの方が動作が軽快になります。

JavaScript】関連記事