实现带返回最后计算结果的underscore _.throttle函数遇阻求助
问题分析与修复方案
你的核心问题在于混淆了节流和记忆化的逻辑,同时第一个版本完全失去了节流的作用,第二个版本的缓存逻辑不符合需求:
现有代码的问题
- 第一个版本:无论是否处于节流等待状态,都会先执行原函数
func,这直接违背了节流的核心——等待期内不执行原函数,相当于只做了延迟解锁,根本没节流。 - 第二个版本:用参数作为key缓存结果,但你的需求是「节流等待时返回最后一次计算的结果」,而不是「相同参数返回缓存」。如果等待期内传入新的参数,
cache[key]会是undefined,自然无法得到正确结果。
修正后的实现
我们只需要保存上一次执行原函数的结果,不需要按参数缓存。当处于节流等待状态时,直接返回这个结果;非等待状态则执行原函数、更新结果并启动节流定时器:
_.throttle = function (func, wait) { let isThrottled = false; let lastResult; // 只保存最后一次执行的结果 return function (...args) { // 处于节流状态,直接返回上一次结果 if (isThrottled) { return lastResult; } // 非节流状态,执行原函数并保存结果 lastResult = func.apply(this, args); isThrottled = true; // 等待时间后解锁节流 setTimeout(() => { isThrottled = false; }, wait); // 返回本次执行的结果 return lastResult; }; };
逻辑说明
isThrottled:标记当前是否处于节流等待期lastResult:存储上一次执行原函数得到的结果- 当调用节流后的函数时:
- 如果在等待期,直接返回
lastResult,不执行原函数 - 如果不在等待期,执行原函数,更新
lastResult,然后启动定时器锁定节流状态
- 如果在等待期,直接返回
- 定时器到期后,解锁节流状态,允许下一次调用执行原函数
测试验证
用你提到的字符串反转函数测试:
const reverseStr = (str) => str.split('').reverse().join(''); const throttledReverse = _.throttle(reverseStr, 2000); console.log(throttledReverse('abc')); // 输出 'cba',执行原函数 console.log(throttledReverse('def')); // 输出 'cba',处于节流等待,返回上一次结果 setTimeout(() => console.log(throttledReverse('ghi')), 2500); // 输出 'ihg',节流到期,执行原函数
内容的提问来源于stack exchange,提问作者Niels Koop
相关产品推荐
相关产品推荐

