EdwardZZZ / articles

工作点滴记录
2 stars 0 forks source link

函数节流(throttle)、函数去抖(debounce) #26

Open EdwardZZZ opened 7 years ago

EdwardZZZ commented 7 years ago

简单实现

const debounce = (action, idle = 100) => {
    let last;
    return function(...props) {
        last && clearTimeout(last);
        last = setTimeout(() => {
            action.apply(this, props)
        }, idle)
    }
}

const throttle = (action, delay = 100) => {
    let last = 0;
    return function(...props){
        const curr = +new Date();
        if(curr - last > delay){
            action.apply(this, props);
            last = curr;
        }
    }
}

const throttle = (action, delay = 100) => {
    let flag = false;
    return function(...props){
        if (flag) return;

        action.apply(this, props);
        flag = true;
        setTimeout(() => {
            flag = false;
        }, delay);
    }
}
EdwardZZZ commented 3 years ago
class Trigger {
    static list = [];

    static run(fn) {
        const { list } = Trigger;

        list.push(fn)

        Promise.resolve().then(() => {
            if (list.length === 0) return;

            list[list.length - 1]();

            list.length = 0;
        })
    }
}

[...Array(10)].forEach((_, i) => {
    Trigger.run(() => {
        console.log('1', i);
    });
});

[...Array(10)].forEach((_, i) => {
    Trigger.run(() => {
        console.log('2', i);
    });
});

setTimeout(()=> {
    [...Array(10)].forEach((_, i) => {
        Trigger.run(() => {
            console.log('3', i);
        });
    });
});
EdwardZZZ commented 3 years ago

function debounceMicro() {
    const list = [];
    return function(fn) {
        list.push(fn)

        Promise.resolve().then(() => {
            if (list.length === 0) return;

            list[list.length - 1]();

            list.length = 0;
        });
    }
}

const trigger = debounceMicro();

[...Array(10)].forEach((_, i) => {
    trigger(() => {
        console.log('11', i);
    });
});

[...Array(10)].forEach((_, i) => {
    trigger(() => {
        console.log('12', i);
    });
});

setTimeout(()=> {
    [...Array(10)].forEach((_, i) => {
        trigger(() => {
            console.log('13', i);
        });
    });
});
EdwardZZZ commented 3 years ago
function useThrottle(cb, delay) {
    const options = {
        leading: true,
        trailing: false
    }; // add custom lodash options
    const cbRef = useRef(cb);
    // use mutable ref to make useCallback/throttle not depend on `cb` dep
    useEffect(() => {
        cbRef.current = cb;
    });
    return useCallback(
        throttle((...args) => cbRef.current(...args), delay, options),
        [delay]
    );
}

function useDebounce(cb, delay) {
    const inputsRef = useRef(cb); // mutable ref like with useThrottle
    useEffect(() => {
        inputsRef.current = {
            cb,
            delay
        };
    }); //also track cur. delay
    return useCallback(
        debounce((...args) => {
            // Debounce is an async callback. Cancel it, if in the meanwhile
            // (1) component has been unmounted (see isMounted in snippet)
            // (2) delay has changed
            if (inputsRef.current.delay === delay && isMounted())
                inputsRef.current.cb(...args);
        }, delay, options),
        [delay, debounce]
    );
}