JS関数の節流と分時関数


関数節流と分時関数は、JS高次関数の2つの特定の応用シーンであり、それらはいずれも関数を戻り値returnとして関数の外部にある.
JS関数の流れ
関数の流れは,関数が呼び出される周波数を減少させることであり,主にDOMイベントの曝露問題に対して提案された解決法である.例えば、resize、mousemoove、mouseover、mouseout、keydown、keyupなどの事件を使って、いずれも頻繁に事件を触発します.これらのイベントの処理関数には、Ajax要求、データベースクエリ、DOMエルゴードなどの大量の時間消費動作が含まれている場合、ブラウザを崩壊させ、ユーザ体験に深刻な影響を与える可能性がある.例えば、大型ネットワーク・プラットフォームのナビゲーションバーでは、mouseoverとmouseoutの移動の早さがブラウザ処理に与える負担を軽減するため、特にAjaxの呼び出しに伴うサーバーへの負担を軽減するために、関数節流処理が行われます.
【設計思想】
コードを中断したまま繰り返し実行させます.
【実現方法】
タイマーを使って関数を節流します.
//        ,  method        ,delay        ,     
function throttle(mothod, delay) {
    var timer = null;  //     
    return function () {  //      
        var context = this, args = arguments;  //          
        clearTimeout(timer);  //         
        timer = setTimeout(function () {  //       ,         
            method.apply(context, args);  //       
        }, delay);
    }
}
【アプリケーションコード】
テキストボックスのkeyupイベントとウィンドウのresizeイベントを設計して、ブラウザでウィンドウをドラッグしたり、テキストボックスに文字を入力して、コンソールでイベントの応答回数と速度を調べます.


    function queryData(text) { console.log("  :" + text); }
    var input = document.getElementById("search");
    input.addEventListener("keyup", function(event) {queryData(this.value); });
    var n = 0;  //      
    function f() { console.log("    :" + ++n); }
    window.onresize = f;
観測により,ドラッグして窓を変えた瞬間,resizeイベントは数十回応答したことが分かった.テキストボックスに文字を入力すると、keyupイベントはすぐに応答して、ユーザーが単語を入力し終わるまで待つことができません.以下では、throttle()パッケージ関数を使用して、上のイベント処理関数をスロットル関数に変換し、遅延時間を500ミリ秒に設定します.
input.addEventListener("keyup", function(event) {
    throttle(queryData, 500) (this.value);
});
window.onresize = throttle(f, 500);
 
再試験を行うと、一度ウィンドウをドラッグしてサイズを変更し、一度だけ応答します.テキストボックスに文字を入力しても、すぐには応答しません.半秒待ってから、入力した文字が表示されます.
JS分時関数
時関数と関数の節流の設計構想は似ていますが、応用シーンは少し違っています.大量操作がページの性能に影響を与える場合、一度に大量のDOMノードをページに追加すると、ブラウザのレンダリングに影響を与えることは明らかであり、極端な場合には、カートンや仮死などの現象が発生する可能性がある.
【設計の考え方】
 バッチ処理を行い、1秒を100個のノードを作成し、200ミリ秒ごとに100個のノードを作成するなどします.
【実現コード】
 
var timeChunk = function (ary, fn, count) {
    var t;
    var start = function () {
        for (var i = 0; i < Math.min(count || 1, ary.length); i ++) {
            var obj = ary.shift();
            fn(obj);
        }
    }
    return function () {
        t = setInterval (function () {
            if (ary.length === 0) {  //             
                return clearInterval(t);
            }
            start();
        }, 200);  //         ,           
    };
};
timeChunk関数は3つのパラメータを受信し、1番目のパラメータはバッチ動作に必要なデータを表し、2番目のパラメータはバッチ動作の論理関数をカプセル化し、3番目のパラメータはバッチ動作の数を表します.下のページに10,000のspan要素を挿入します.膨大な数のため、ここでタイムシェア関数を使ってバッチ操作を行います.
var arr = [];
for (var i = 1; i < 10000; i ++) {
    var span = document.creatElement("span");
    span.style.padding = "6px 12px";
    span.innerHTML = i;
    arr.push(span);
}
var fn = function (obj) {
    document.body.appendChild(obj);
}
timeChunk(arr, fn, 100) ();