首页 > 解决方案 > 如何使用返回另一个函数的函数?

问题描述

关于返回其他函数的函数如何工作,我从根本上不了解。我有以下油门功能,我使用它来确保不会经常发送命令。它已经完全从 StackOverflow 中提取出来了,我没有写这个。

// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run
// as much as it can, without ever going more than once per `wait` duration;
// but if you'd like to disable the execution on the leading edge, pass
// `{leading: false}`. To disable execution on the trailing edge, ditto.
function throttle(func, wait, options) {
    var context, args, result;
    var timeout = null;
    var previous = 0;
    if (!options) options = {};
    var later = function () {
        previous = options.leading === false ? 0 : Date.now();
        timeout = null;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
    };
    return function () {
        var now = Date.now();
        if (!previous && options.leading === false) previous = now;
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            result = func.apply(context, args);
            if (!timeout) context = args = null;
        } else if (!timeout && options.trailing !== false) {
            timeout = setTimeout(later, remaining);
        }
        return result;
    };
};

我把它绑在一个范围滑块上。这种超基本的解释完美地工作

volSlider = document.querySelector("#slider-vol");
volSlider.oninput = throttle(sendVolumeMessage, 100);

function sendVolumeMessage() {
    console.log(`Throttled Volume ${volSlider.value}`);
}

问题是我也想用那个滑块做非节流的事情。以下不起作用

volSlider = document.querySelector("#slider-vol");
volSlider.oninput = setVolume();

function setVolume() {
    return function () {
        console.log(`Volume ${volSlider.value}`);
        throttle(sendVolumeMessage, 100);
    }
}

function sendVolumeMessage() {
    console.log(`Throttled Volume ${volSlider.value}`);
}

控制台日志显示“Volume 30”或任何数字,但不显示 Throttled Volume。关于函数内部传递函数的工作原理,我不了解什么?显然,我实际上并没有在我的 setVolume 函数中调用油门函数,但我终其一生都无法弄清楚原因。

标签: javascript

解决方案


存储油门并调用它

volSlider = document.querySelector("#slider-vol");
volSlider.oninput = setVolume();

function setVolume() {
    const fnc = throttle(sendVolumeMessage, 100);
    return function () {
        console.log(`Volume ${volSlider.value}`);
        fnc();
    }
}

function sendVolumeMessage() {
    console.log(`Throttled Volume ${volSlider.value}`);
}

或使用 addEventListener 添加两个单独的事件

function otherFunction () {
  console.log(new Date());
}

volSlider = document.querySelector("#slider-vol");
volSlider.addEventListener('input', throttle(sendVolumeMessage, 100));
volSlider.addEventListener('input', otherFunction);

推荐阅读