検索
ホームページウェブフロントエンドjsチュートリアルJavaScriptのスロットル機能Throttleの詳細説明

ブラウザのDOMイベントには、ユーザーの操作に合わせて継続的にトリガーされるイベントがいくつかあります。たとえば、ブラウザ ウィンドウのサイズを変更し (resize)、ブラウザ ページをスクロールし (scroll)、マウスを移動します (mousemove)。つまり、ユーザーがこれらのブラウザ操作をトリガーすると、対応するイベント処理メソッドがスクリプトにバインドされている場合、このメソッドは継続的にトリガーされます。

これは私たちが望んでいることではありません。イベント処理メソッドが比較的大きく、DOM 操作が複雑で、そのようなイベントが継続的にトリガーされる場合、パフォーマンスの損失が発生し、ユーザー エクスペリエンスの低下につながることがあるためです (UI の応答は遅い、ブラウザがフリーズするなど)。したがって、一般的に言えば、対応するイベントに遅延実行ロジックを追加します。

通常、この関数を実装するには次のコードを使用します:

var COUNT = 0;
function testFn() { console.log(COUNT++); }
// 浏览器resize的时候
// 1. 清除之前的计时器
// 2. 添加一个计时器让真正的函数testFn延后100毫秒触发
window.onresize = function () {
    var timer = null;
    clearTimeout(timer);

    timer = setTimeout(function() {
        testFn();
    }, 100);
};

注意してください。上記のコードは実際には間違っていることがわかります。これは初心者が犯す問題です。setTimeout 関数の戻り値は相対値に保存する必要があります。そうしないと、サイズが変更されるたびに新しいタイマーが生成され、送信した効果が得られないため、コードを修正しました:

var timer = null;
window.onresize = function () {
    clearTimeout(timer);
    timer = setTimeout(function() {
        testFn();
    }, 100);
};

現時点では、コードは正常ですが、もう 1 つ新しい問題があります。 - グローバル変数タイマーが生成されます。これは望ましくないことです。このページにタイマーと呼ばれる他の機能がある場合、異なるコードが競合することになります。この問題を解決するには、JavaScript の言語機能、

closure

クロージャを使用する必要があります。関連する知識がある読者は、MDN にアクセスして詳細を学ぶことができます。 変更されたコードは次のとおりです:

/**
 * 函数节流方法
 * @param Function fn 延时调用函数
 * @param Number delay 延迟多长时间
 * @return Function 延迟执行的方法
 */
var throttle = function (fn, delay) {
    var timer = null;

    return function () {
        clearTimeout(timer);
        timer = setTimeout(function() {
            fn();
        }, delay);
    }
};
window.onresize = throttle(testFn, 200, 1000);
タイマーを内部に配置し、遅延処理関数を返すためにクロージャー関数 (スロットル調整) を使用します。そのため、タイマー変数は次のようになります。外部からは見えませんが、内部遅延関数がトリガーされたときにタイマー変数にアクセスすることもできます。

もちろん、この書き方は初心者にとっては理解しにくいです。理解できるように書き方を変更することができます:

var throttle = function (fn, delay) {
    var timer = null;

    return function () {
        clearTimeout(timer);
        timer = setTimeout(function() {
            fn();
        }, delay);
    }
};

var f = throttle(testFn, 200);
window.onresize = function () {
    f();
};

理解すべき主なポイントは次のとおりです:

Throttle

呼び出された後に返される関数は実際のものです。 onresize 関数 がトリガーされたときに呼び出す必要があります。このメソッドは完璧に近いように見えますが、実際の使用ではそうではありません。例:

ユーザーがブラウザウィンドウのサイズを
継続的に

変更すると、遅延処理関数は一度も実行されなくなります

そのため、別の関数を追加する必要があります: ユーザーがサイズ変更をトリガーしたとき、それは
である必要があります。一定時間 一定期間内に少なくとも1回トリガーします

。この判定条件は、各関数の呼び出し時に、最後の呼び出し時刻から現在時刻を減算することになります。次に、その差が一定期間より大きい場合は、直接トリガーされます。それ以外の場合は、タイムアウトの遅延ロジックが引き続き使用されます。 次のコードで注意する必要があるのは:

    前の変数にはタイマーと同様の機能があり、最後の識別を記録し、相対グローバル変数である必要があります
  1. ロジックフローが「at」の場合最小トリガー「1 回」ロジックの場合、関数呼び出しを現在の時刻にリセットする必要があります。簡単に言うと、次回と比較して、前回の時刻が実際には現在の時刻です
  2. /**
     * 函数节流方法
     * @param Function fn 延时调用函数
     * @param Number delay 延迟多长时间
     * @param Number atleast 至少多长时间触发一次
     * @return Function 延迟执行的方法
     */
    var throttle = function (fn, delay, atleast) {
        var timer = null;
        var previous = null;
    
        return function () {
            var now = +new Date();
    
            if ( !previous ) previous = now;
    
            if ( now - previous > atleast ) {
                fn();
                // 重置上一次开始时间为本次结束时间
                previous = now;
            } else {
                clearTimeout(timer);
                timer = setTimeout(function() {
                    fn();
                }, delay);
            }
        }
    };
  3. 実践:

時間を節約するためにウィンドウをスクロールするシナリオ、つまり、ユーザーがページを下にスクロールするとき、DOM 位置の計算や、DOM 要素の継続的な操作を必要とするその他のアクションなど、いくつかのメソッドの実行を抑制する必要があります

完全なコードは次のとおりです。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>throttle</title>
</head>
<body>
    <p style="height:5000px">
        <p id="demo" style="position:fixed;"></p>
    </p>
    <script>
    var COUNT = 0, demo = document.getElementById(&#39;demo&#39;);
    function testFn() {demo.innerHTML += &#39;testFN 被调用了 &#39; + ++COUNT + &#39;次<br>&#39;;}

    var throttle = function (fn, delay, atleast) {
        var timer = null;
        var previous = null;

        return function () {
            var now = +new Date();

            if ( !previous ) previous = now;
            if ( atleast && now - previous > atleast ) {
                fn();
                // 重置上一次开始时间为本次结束时间
                previous = now;
                clearTimeout(timer);
            } else {
                clearTimeout(timer);
                timer = setTimeout(function() {
                    fn();
                    previous = null;
                }, delay);
            }
        }
    };
    window.onscroll = throttle(testFn, 200);
    // window.onscroll = throttle(testFn, 500, 1000);
    </script>
</body>
</html>

テストには 2 つのケースを使用します。効果は、少なくともトリガーのパラメータを追加し、追加しないことです:

// case 1
window.onscroll = throttle(testFn, 200);
// case 2
window.onscroll = throttle(testFn, 200, 500);

ケース 1

パフォーマンスは次のとおりです: ページのスクロール中に testFN は呼び出されませんプロセス (停止できません) であり、停止時に 1 回呼び出されます。つまり、スロットルでの last setTimeout の実行であると言われており、その効果は図に示すとおりです (元の gif 画像を表示):

ケース 2

は次のように動作します: testFN はページスクロールプロセス中に初めて呼び出されます (停止できません) (少なくとも遅延ロジックから) 500 ミリ秒だけ実行を遅延させ、その後少なくとも 500 ミリ秒ごとに実行します. 効果は図の通りです

ここまでで、達成したい効果は概ね完成しました。読者は、これが指す関数、戻り値のストレージなど、後続の補助的な最適化を自分で理解できます。

引用

    テストコード http://jsbin.com/tanuxegija/edit
  1. 完全版コード http://jsbin.com/jigozuvuko
  2. デバウンス VS スロットル https://github.com /dcorb/デバウンススロットル

上記は JavaScript のスロットル関数 Throttle の詳細な説明です。さらに関連するコンテンツについては、PHP 中国語 Web サイト (www.php.cn) を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

整理总结JavaScript常见的BOM操作整理总结JavaScript常见的BOM操作Jun 01, 2022 am 11:43 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

foreach是es6里的吗foreach是es6里的吗May 05, 2022 pm 05:59 PM

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!