您可以在 github 仓库中找到这篇文章中的所有代码。
异步编程定时器相关的挑战
有时间限制的缓存
class timelimitedcache { constructor() { this._cache = new map(); } set(key, value, duration) { const found = this._cache.has(key); if (found) { cleartimeout(this._cache.get(key).ref); } this._cache.set(key, { value, ref: settimeout(() => { this._cache.delete(key); }, duration), }); return found; } get(key) { if (this._cache.has(key)) { return this._cache.get(key); } else { return -1; } } count() { return this._cache.size; }}// usage exampleconst timelimitedcache = new timelimitedcache();console.log(timelimitedcache.set(1, 'first', 1000)); // => falseconsole.log(timelimitedcache.get(1).value); // => 'first'console.log(timelimitedcache.count()); // => 1 settimeout(() => { console.log(timelimitedcache.count()); // => 0 console.log(timelimitedcache.get(1)); // => -1}, 2000);
登录后复制
取消间隔
/** * @param {function} callback * @param {number} delay * @param {...any} args * @returns {function} */function setcancellableinterval(callbackfn, delay, ...args) { const timerid = setinterval(callbackfn, delay, ...args); return () => { clearinterval(timerid); };}// usage examplelet i = 0;// t = 0:const cancel = setcancellableinterval(() => { i++;}, 100);// t = 50:cancel();// t = 100: i is still 0 because cancel() was called.
登录后复制
取消超时
/** * @param {function} callbackfn * @param {number} delay * @param {...any} args * @returns {function} */function setcancellabletimeout(callbackfn, delay, ...args) { const timerid = settimeout(callbackfn, delay, ...args); return () => { cleartimeout(timerid); };}// usage examplelet i = 0;// t = 0:const cancel = setcancellabletimeout(() => { i++;}, 100);// t = 50:cancel();// t = 100: i is still 0 because cancel() was called.
登录后复制
清除所有超时定时器
/** * cancel all timer from window.settimeout */const timerqueue = [];const originalsettimeout = window.settimeout;window.settimeout = function (callbackfn, delay, ...args) { const timerid = originalsettimeout(callbackfn, delay, ...args); timerqueue.push(timerid); return timerid;}function clearalltimeout() { while (timerqueue.length) { cleartimeout(timerqueue.pop()); }}// usage examplesettimeout(func1, 10000)settimeout(func2, 10000)settimeout(func3, 10000)// all 3 functions are scheduled 10 seconds laterclearalltimeout()// all scheduled tasks are cancelled.
登录后复制
去抖动
/** * @param {function} fn * @param {number} wait * @return {function} */function debounce(fn, wait = 0) { let timerid = null; return function (...args) { const context = this; cleartimeout(timerid); timerid = settimeout(() => { timerid = null; fn.call(context, ...args); }, wait); }}// usage examplelet i = 0;function increment() { i += 1;}const debouncedincrement = debounce(increment, 100);// t = 0: call debouncedincrement().debouncedincrement(); // i = 0// t = 50: i is still 0 because 100ms have not passed.// call debouncedincrement() again.debouncedincrement(); // i = 0// t = 100: i is still 0 because it has only// been 50ms since the last debouncedincrement() at t = 50.// t = 150: because 100ms have passed since// the last debouncedincrement() at t = 50,// increment was invoked and i is now 1 .
登录后复制
风门
/** * @param {function} fn * @param {number} wait * @return {function} */function throttle(fn, wait = 0) { let shouldthrottle = false; return function (...args) { if (shouldthrottle) { return; } shouldthrottle = true; settimeout(() => { shouldthrottle = false; }, wait); fn.call(this, ...args); }}// usage examplelet i = 0;function increment() { i++;}const throttledincrement = throttle(increment, 100);// t = 0: call throttledincrement(). i is now 1.throttledincrement(); // i = 1// t = 50: call throttledincrement() again.// i is still 1 because 100ms have not passed.throttledincrement(); // i = 1// t = 101: call throttledincrement() again. i is now 2.// i can be incremented because it has been more than 100ms// since the last throttledincrement() call at t = 0.throttledincrement(); // i = 2
登录后复制
重复间隔
const url = 'https://fastly.picsum.photos/id/0/5000/3333.jpg?hmac=_j6ghy5fcfsd6tvtcv74zxivkjspifr9b8w34xeqmvu';function fetchdata(url) { return fetch(url) .then((response) => { if (!response.ok) { throw new error(`error: ${response.status}`); } return response.blob(); }) .then((data) => { console.log(data); }) .catch((err) => { console.log(`error: ${err}`); });}function repeat(callbackfn, delay, count) { let currentcount = 0; const timerid = setinterval(() => { if (currentcount clearinterval(timerid), }}// usage exampleconst cancel = repeat(() => fetchdata(url), 2000, 5);settimeout(() => { cancel.clear();}, 11000);
登录后复制
可恢复间隔
/** * @param {function} callbackfn * @param {number} delay * @param {...any} args * @returns {{start: function, pause: function, stop: function}} */function createresumableinterval(callbackfn, delay, ...args) { let timerid = null; let stopped = false; function cleartimer() { clearinterval(timerid); timerid = null; } function start() { if (stopped || timerid) { return; } callbackfn(...args); timerid = setinterval(callbackfn, delay, ...args); } function pause() { if (stopped) { return; } cleartimer(); } function stop() { stopped = true; cleartimer(); } return { start, pause, stop, };}// usage examplelet i = 0;// t = 0:const interval = createresumableinterval(() => { i++;}, 10);// t = 10:interval.start(); // i is now 1.// t = 20: callback executes and i is now 2.// t = 25:interval.pause();// t = 30: i remains at 2 because interval.pause() was called.// t = 35:interval.start(); // i is now 3.// t = 45: callback executes and i is now 4.// t = 50:interval.stop(); // i remains at 4.
登录后复制
实现 setinterval()
/** * @param {function} callbackfn * @param {number} delay * @return {object} */// use `requestanimationframe`function mysetinterval(callbackfn, delay) { let timerid = null; let start = date.now(); // loop function loop() { const current = date.now(); if (current - start >= delay) { callbackfn(); start = current; } timerid = requestanimationframe(loop); } // run loop loop(); return { clear: () => cancelanimationframe(timerid), }}const interval = mysetinterval(() => { console.log('interval tick');}, 1000);// cancelsettimeout(() => { interval.clear();}, 5000);// use `settimeout`function mysetinterval(callbackfn, delay) { let timerid = null; let start = date.now(); let count = 0; // loop function loop() { const drift = date.now() - start - count * delay; count += 1; timerid = settimeout(() => { callbackfn(); loop(); }, delay - drift); } // run loop loop(); return { clear: () => cleartimeout(timerid), }}const interval = mysetinterval(() => { console.log('interval tick');}, 1000);// cancelsettimeout(() => { interval.clear();}, 5000);
登录后复制
实现 settimeout()
function setTimeout(callbackFn, delay) { let elapsedTime = 0; const interval = 100; const intervalId = setInterval(() => { elapsedTime += interval; if (elapsedTime >= delay) { clearInterval(intervalId); callbackFn(); } }, interval);}// Usage examplemySetTimeout(() => { console.log('This message is displayed after 2 seconds.');}, 2000);
登录后复制
参考
窗口:settimeout() 方法 – mdn窗口:setinterval() 方法 – mdn窗口:clearinterval() 方法 – mdn窗口:cleartimeout() 方法 – mdn2715。超时取消 – leetcode2725。间隔取消 – leetcode2622。有时间限制的缓存 – leetcode2627。反跳 – leetcode2676。油门 – leetcode速率限制 – wikipedia.org28。实现clearalltimeout() – bfe.dev4.实现基本的throttle() – bfe.dev5.使用前导和尾随选项实现throttle() – bfe.dev6.实现基本的 debounce() – bfe.dev7.使用前导和尾随选项实现 debounce() – bfe.devjavascript 异步:练习、实践、解决方案 – w3resource伟大的前端
以上就是计时器 – JavaScript 挑战的详细内容,更多请关注【创想鸟】其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。
发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2658432.html