白猫のメモ帳

C#とかJavaとかJavaScriptとかHTMLとか機械学習とか。

サジェストでajaxのリクエストをしまくらないように調整する

こんにちは。

体調を崩していたり、プライベートがいろいろゴタゴタしていまして、
随分久しぶりになってしまいました。

今回はJavaScriptのお話。

サジェストって

f:id:Shiro-Neko:20190803183444p:plain

こういうやつです。
1文字入力するごとに候補がでてくるやつ。

基本的には「onkeyup」のイベントを拾って、ajaxでサーバーサイドに処理を投げたりします。
もちろんクライアントサイドで処理しても良いですよ。
(「keydown」は直前に入力した内容がvalueで取れませんので「keyup」)

ただ、1文字入力するごとにっていうことは、
「ねこ」って打とうとしたときに、
「n」「ね」「ねk」「ねこ」って4回リクエストが飛んでしまうんですよね。

リソースが潤沢で、しっかりとキャッシュとかすれば気にならないかもしれないですが、
できることなら余計なものは飛ばしたくないです。

ちょっと待つ

というわけで、ちょっと待つというシンプルな手法を取ります。
ユーザが連続して入力中の間は処理を待っていて、入力が終わっただろうというタイミングでリクエストを投げます。

ちょっと待つといえばsetTimeoutですね。

var timeout;
function anythingSearch() {
    clearTimeout(timeout);
    timeout = setTimeout(function() {
        // なんか検索処理
    }, 200);
}

が、なんか変なスコープに変数作るの嫌ですよね。
(無名関数で囲い込めばいいじゃんというのは聞かなかったことにします)

でもそういえばsetTimeoutの戻り値ってタイムアウトの関数自体ではなくて、なんかIDみたいなやつなのでした。
MDNにも以下のような記載があります。

戻り値 timeoutID は、setTimeout() を呼び出して作成したタイマーを識別する正の整数値です。
この値は、タイムアウトをキャンセルするために clearTimeout() へ渡すことができます。

ということは要素自体のdata属性に入れとけばよいのでは?

function anythingSearch() {
    clearTimeout(this.dataset.timeout);
    var timeout = setTimeout(function() {
        // なんか検索処理
    }, 200);
    this.dataset.timeout = timeout ;
}

とふと思ったのでした。
現場からは以上です。