【问题标题】:Trying to use setInterval to make a throttling function unsuccessfully尝试使用 setInterval 使节流功能失败
【发布时间】:2022-01-14 12:49:58
【问题描述】:

我正在尝试返回一个函数,该函数仅每“等待”毫秒调用一次回调函数“func”。

在“等待”期间对回调“func”的额外调用不应被调用或排队。

这就是我目前所拥有的......

function throttle(func, wait) {
    function inner(...args) {
        setInterval(func(...args), wait);
    }
    return inner;
}

当我通过测试算法运行代码时,出现以下错误:

  1. “节流函数应该只能在指定时间后才能再次调用”

这是测试算法...

let counter = 0;
const incr = () => counter++;
const throttledIncr = throttle(incr, 32);
throttledIncr();
throttledIncr();
setTimeout(() => {
  expect(counter).to.eql(1);
  throttledIncr();
  setTimeout(() => {
    expect(counter).to.eql(2);
    done();
  }, 32);
}, 32);
  1. “节流函数返回它们的值”

这是测试算法...

let counter = 0;
const incr = () => ++counter;
const throttledIncr = throttle(incr, 32);
const result = throttledIncr();
setTimeout(() => {
  expect(result).to.eql(1);
  expect(counter).to.eql(1);
  done();
}, 64);
  1. “重复调用的节流函数应遵守时间限制”

这是测试算法...

const incr = () => ++counter;
const throttledIncr = throttle(incr, 64);
const results = [];
const saveResult = () => results.push(throttledIncr());
saveResult();
saveResult();
setTimeout(saveResult, 32);
setTimeout(saveResult, 80);
setTimeout(saveResult, 96);
setTimeout(saveResult, 180);
setTimeout(() => {
  expect(results[0]).to.eql(1);
  expect(results[1]).to.be(undefined);
  expect(results[2]).to.be(undefined);
  expect(results[3]).to.eql(2);
  expect(results[4]).to.be(undefined);
  expect(results[5]).to.eql(3);
  done();
}, 192);

我对每个案例的问题:

  1. 如何防止函数再次被调用?
  2. 为什么 ISNT 我的函数返回值?我无法用给定的测试算法推断出什么或如何返回一个值。
  3. “重复调用的节流函数应遵守时间限制”是什么意思?这似乎与第一个错误相矛盾。没有提到设置时间限制,所以我不相信在这里使用 setTimeout 是他们的意思......

【问题讨论】:

    标签: javascript callback setinterval throttling


    【解决方案1】:

    如何防止函数再次被调用?

    function throttle(func, wait) {
        function inner(...args) {
            setInterval(func(...args), wait);
        }
        return inner;
    }
    

    首先,您上面的代码没有按照您的预期执行。目前,每次调用 throttle 时,都会将 func 添加到事件循环中,以按时间间隔执行。

    所以当您调用throttleIncr 5 次时,您将incr 添加到要被调用五次的事件循环中。

    一种方法 (imo) 是跟踪上次调用 throttle(func) 的时间。下次调用throttle(func) 时,检查等待时间是否已过。如果是这样,请调用 func 并保存新时间。如果没有,请返回。

    为什么 ISNT 我的函数返回值?我无法用给定的测试算法推断出什么或如何返回一个值。

    您的 incr 函数正在返回值,但是您的 throttle 函数将其置于事件循环中,用于异步执行,因此返回值不可用。

    “重复调用的节流函数应该遵守时间限制”是什么意思?这似乎与第一个错误相矛盾。

    这不是 javascript 错误,可能是来自您正在调用的测试的自定义失败消息。

    【讨论】:

    • 感谢您抽出宝贵时间回复!当你说,“首先,你上面的代码没有做你期望它做的事情。目前每次你调用throttle,你都是在事件循环中添加func,以间隔执行。”这怎么没有做我想做的事?我知道它被添加到偶数循环中......你是在暗示我不应该使用闭包函数吗?我将尝试想一种方法来“跟踪上次调用throttle(func) 的时间”。谢谢你的主意。你关于偶数循环的第三条评论让我相信我不需要闭包函数
    • @DaShaman 根据您对节流阀的要求,节流函数应该只允许您在给定时间段内最多执行一次函数,并且应该忽略所有其他调用。因此,如果您在窗口中调用节流增量函数 10 次,它只会增量一次。相反,您在实现中所做的是将函数排队等待一段时间后执行。不仅如此,通过使用setInterval,该函数将在每次间隔过去时继续一遍又一遍地执行。因此,我对该函数的评论没有达到您的预期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-10
    • 1970-01-01
    • 1970-01-01
    • 2016-03-05
    • 2021-05-16
    • 2015-06-28
    • 1970-01-01
    相关资源
    最近更新 更多