Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions Modern Development/Debounce and Throttle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Debounce and Throttle

Utility functions to control how often a function executes during frequent events.

## Overview

**Debounce** - Waits until user stops action before executing (e.g., search input, auto-save)
**Throttle** - Limits execution to once per time interval (e.g., scroll, resize)

## Files

- `debounce.js` - 3 debounce variations
- `throttle.js` - 4 throttle variations
- `combined-usage.js` - Real-world examples

## Quick Examples

### Debounce
```javascript
const handleSearch = debounce((query) => {
// API call after user stops typing
fetch(`/api/search?q=${query}`);
}, 300);

inputElement.addEventListener('input', e => handleSearch(e.target.value));
```

### Throttle
```javascript
const handleScroll = throttle(() => {
// Update every 300ms during scroll
updateScrollBar();
}, 300);

window.addEventListener('scroll', handleScroll);
```

## Use Cases

**Debounce:** search input, auto-save, form validation
**Throttle:** scroll events, window resize, animations
69 changes: 69 additions & 0 deletions Modern Development/Debounce and Throttle/combined-usage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Search with debounce - waits for user to stop typing
class SearchBox {
constructor(inputSelector, onSearch) {
this.input = document.querySelector(inputSelector);
this.onSearch = onSearch;
this.debouncedSearch = debounce((query) => {
if (query.length > 2) this.onSearch(query);
}, 300);
this.input.addEventListener('input', e => this.debouncedSearch(e.target.value));
}
}

// Auto-save form after user stops typing
class AutoSaveForm {
constructor(formSelector, saveUrl) {
this.form = document.querySelector(formSelector);
this.saveUrl = saveUrl;
this.debouncedSave = debounce(() => this.save(), 1000);
this.form.addEventListener('input', () => this.debouncedSave());
}

async save() {
const data = new FormData(this.form);
try {
await fetch(this.saveUrl, {
method: 'POST',
body: new URLSearchParams(data)
});
console.log('Saved');
} catch (e) {
console.error('Save failed', e);
}
}
}

// Handle window resize with throttle
class ResponsiveLayout {
constructor() {
this.throttledResize = throttle(() => this.handleResize(), 500);
window.addEventListener('resize', this.throttledResize);
}

handleResize() {
const width = window.innerWidth;
if (width < 768) {
document.body.classList.add('mobile');
} else {
document.body.classList.remove('mobile');
}
}
}

// Scroll detection with throttle
class ScrollHandler {
constructor() {
this.throttledScroll = throttle(() => {
const pos = window.scrollY;
const docHeight = document.documentElement.scrollHeight;
if (pos + window.innerHeight >= docHeight - 100) {
this.loadMore();
}
}, 300);
window.addEventListener('scroll', this.throttledScroll);
}

loadMore() {
console.log('Load more content');
}
}
37 changes: 37 additions & 0 deletions Modern Development/Debounce and Throttle/debounce.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Basic debounce - delays function execution until after user stops action
function debounce(func, wait) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}

// Debounce with cancel method
function debounceWithCancel(func, wait) {
let timeout;
const debounced = function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
debounced.cancel = () => clearTimeout(timeout);
return debounced;
}

// Debounce with flush - execute immediately
function debounceWithFlush(func, wait) {
let timeout, lastArgs, lastThis;
const debounced = function(...args) {
lastArgs = args;
lastThis = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(lastThis, lastArgs), wait);
};
debounced.flush = () => {
if (timeout) {
clearTimeout(timeout);
func.apply(lastThis, lastArgs);
}
};
return debounced;
}
73 changes: 73 additions & 0 deletions Modern Development/Debounce and Throttle/throttle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Basic throttle - limit function execution to once per interval
function throttle(func, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}

// Throttle with timestamp - more precise timing
function throttleWithTimestamp(func, limit) {
let lastRan;
return function(...args) {
if (!lastRan) {
func.apply(this, args);
lastRan = Date.now();
} else {
const remaining = limit - (Date.now() - lastRan);
if (remaining <= 0) {
func.apply(this, args);
lastRan = Date.now();
}
}
};
}

// Throttle with leading and trailing options
function throttleAdvanced(func, wait, options = {}) {
const { leading = true, trailing = false } = options;
let timeout, previous = 0, lastArgs, lastThis;

const throttled = function(...args) {
const now = Date.now();
if (!previous && !leading) previous = now;

const remaining = wait - (now - previous);
lastArgs = args;
lastThis = this;

if (remaining <= 0) {
clearTimeout(timeout);
timeout = null;
previous = now;
func.apply(this, args);
} else if (!timeout && trailing) {
timeout = setTimeout(() => {
previous = leading ? Date.now() : 0;
timeout = null;
func.apply(lastThis, lastArgs);
}, remaining);
}
};
throttled.cancel = () => {
clearTimeout(timeout);
previous = 0;
};
return throttled;
}

// Throttle using requestAnimationFrame for smooth animation
function throttleRAF(func) {
let frameId = null;
return function(...args) {
if (frameId) return;
frameId = requestAnimationFrame(() => {
func.apply(this, args);
frameId = null;
});
};
}
41 changes: 41 additions & 0 deletions Modern Development/ECMASCript 2021/Debounce and Throttle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Debounce and Throttle

Utility functions to control how often a function executes during frequent events.

## Overview

**Debounce** - Waits until user stops action before executing (e.g., search input, auto-save)
**Throttle** - Limits execution to once per time interval (e.g., scroll, resize)

## Files

- `debounce.js` - 3 debounce variations
- `throttle.js` - 4 throttle variations
- `combined-usage.js` - Real-world examples

## Quick Examples

### Debounce
```javascript
const handleSearch = debounce((query) => {
// API call after user stops typing
fetch(`/api/search?q=${query}`);
}, 300);

inputElement.addEventListener('input', e => handleSearch(e.target.value));
```

### Throttle
```javascript
const handleScroll = throttle(() => {
// Update every 300ms during scroll
updateScrollBar();
}, 300);

window.addEventListener('scroll', handleScroll);
```

## Use Cases

**Debounce:** search input, auto-save, form validation
**Throttle:** scroll events, window resize, animations
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Search with debounce - waits for user to stop typing
class SearchBox {
constructor(inputSelector, onSearch) {
this.input = document.querySelector(inputSelector);
this.onSearch = onSearch;
this.debouncedSearch = debounce((query) => {
if (query.length > 2) this.onSearch(query);
}, 300);
this.input.addEventListener('input', e => this.debouncedSearch(e.target.value));
}
}

// Auto-save form after user stops typing
class AutoSaveForm {
constructor(formSelector, saveUrl) {
this.form = document.querySelector(formSelector);
this.saveUrl = saveUrl;
this.debouncedSave = debounce(() => this.save(), 1000);
this.form.addEventListener('input', () => this.debouncedSave());
}

async save() {
const data = new FormData(this.form);
try {
await fetch(this.saveUrl, {
method: 'POST',
body: new URLSearchParams(data)
});
console.log('Saved');
} catch (e) {
console.error('Save failed', e);
}
}
}

// Handle window resize with throttle
class ResponsiveLayout {
constructor() {
this.throttledResize = throttle(() => this.handleResize(), 500);
window.addEventListener('resize', this.throttledResize);
}

handleResize() {
const width = window.innerWidth;
if (width < 768) {
document.body.classList.add('mobile');
} else {
document.body.classList.remove('mobile');
}
}
}

// Scroll detection with throttle
class ScrollHandler {
constructor() {
this.throttledScroll = throttle(() => {
const pos = window.scrollY;
const docHeight = document.documentElement.scrollHeight;
if (pos + window.innerHeight >= docHeight - 100) {
this.loadMore();
}
}, 300);
window.addEventListener('scroll', this.throttledScroll);
}

loadMore() {
console.log('Load more content');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Basic debounce - delays function execution until after user stops action
function debounce(func, wait) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}

// Debounce with cancel method
function debounceWithCancel(func, wait) {
let timeout;
const debounced = function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
debounced.cancel = () => clearTimeout(timeout);
return debounced;
}

// Debounce with flush - execute immediately
function debounceWithFlush(func, wait) {
let timeout, lastArgs, lastThis;
const debounced = function(...args) {
lastArgs = args;
lastThis = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(lastThis, lastArgs), wait);
};
debounced.flush = () => {
if (timeout) {
clearTimeout(timeout);
func.apply(lastThis, lastArgs);
}
};
return debounced;
}
Loading
Loading