Javascript 函數節流

解讀

函數節流(throttle),指的是某個函數在必定時間間隔內(例如 3 秒)只執行一次,在這 3 秒內產生函數調用請求直接無視,也不會延長時間間隔。3 秒間隔結束後第一次遇到新的函數調用會觸發執行,而後在這新的 3 秒內依舊無視新的函數調用請求,以此類推。react

快速記憶:安安靜靜地作好這一件事,無論你怎麼打擾。瀏覽器

場景

被頻繁調用的場景。若是有大量計算,頻繁操做 DOM,資源加載等行爲,可能會致使 UI 卡頓(線程阻塞),嚴重會致使瀏覽器奔潰。app

  • 監聽 Window 對象的 resizescroll 等事件;
  • 拖拽監聽 mousemove 事件;
  • 文字輸入時,對字符串處理或實時搜索;
  • ...

自我實現

  • 定時器。
  • 時間戳。記錄上次執行的時間戳,而後每次觸發事件執行回調,回調中判斷當前時間戳距離上次時間戳的間隔是否達到時間差,若是達到則執行,並更新上次執行的時間戳,如此循環。
// 0.1.1/throttle.js
/** * * @param {Function} callback 回調函數 * @param {Number} wait 間隔時間 * * @return {Function} 節流函數 */
function throttle(callback, wait = 3000) {
    let timer = null;
    let startTime;
    return function () {
        const ctx = this;
        const args = arguments;
        const now = +new Date();
        if (startTime && now < startTime + wait) {
            clearTimeout(timer);
            timer = setTimeout(function () {
                startTime = now;
                callback.apply(ctx, args);
            }, wait);
        } else {
            startTime = now;
            callback.apply(ctx, args);
        }
    }
}
複製代碼

網頁使用

// 0.1.1/throttle.page.js
const body = document.querySelector('body');
const btn = document.createElement('div');
btn.style = 'cursor: pointer; padding: 10px; background:red; border-radius: 5px; text-align: center; color:#fff;';
btn.innerHTML = '函數節流默認 3 秒';
body.append(btn);

function callback() {
    console.log('pr');
}
btn.addEventListener('click', throttle(callback));
複製代碼

React.js

import React from 'react';
import { throttle } from './throttle';

// 使用
export default class ThrottleInReact extends React.Component {
    constructor() {
        super();
        this.change = throttle(e => {
            console.log(e.target.value);
        }, 1000);
    }

    onWindowResize = () => {
        console.log('resize');
    }

    onRemoveWindowResize = () => {
        console.log('remove resize');
    }

    handleChange = e => {
        e.persist();
        this.change(e);
    }

    render() {
        return (
            <input onChange={this.handleChange} />
        )
    }

    componentDidMount() {
        window.addEventListener('resize', throttle(this.onWindowResize, 60));
    }

    componentWillUnmount() {
       window.removeEventListener('resize', throttle(this.onRemoveWindowResize, 60));
    }
}
複製代碼

你能夠

上一篇:JavaScript 執行上下文和執行棧函數

下一篇:Javascript 函數防抖post

相關文章
相關標籤/搜索