DevPrep
  • Interview Prep
  • Projects
  • Resources
  • Pricing
  • About Us
Submit Question
DevPrep
  • Pricing
  • About Us
Submit Question

Practice

  • JavaScript
  • DSA
  • Machine Coding
  • System Design

Resources

  • Learning Tracks
  • Articles
  • Roadmaps
  • Compare Concepts
  • Glossary
  • Developer Tools
  • All Questions

Company

  • About
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
DevPrep

© 2026 DevPrep. All rights reserved.

← Back to Questions
HardJavaScript

Implement Throttle with Cancel and Flush

51 views

Problem Statement

In React applications and complex UIs, we need the ability to cancel pending throttled operations (e.g., on component unmount) and flush pending calls immediately (e.g., before navigation). Implement a throttle with full lifecycle control.

Requirements

Implement a throttle(func, wait) function that returns a throttled function with:

  • cancel() - cancels any pending trailing invocation
  • flush() - immediately executes pending trailing invocation (if any)
  • pending() - returns boolean indicating if a trailing call is pending
  • Both leading and trailing enabled by default

Example Usage

const syncToServer = (data) => {
  console.log(`Syncing: ${JSON.stringify(data)}`);
};

const throttledSync = throttle(syncToServer, 2000);

// User makes rapid changes
throttledSync({ v: 1 }); // Executes immediately (leading)
throttledSync({ v: 2 }); // Queued for trailing
throttledSync({ v: 3 }); // Replaces queue

console.log(throttledSync.pending()); // true

// Option 1: Cancel - discard pending
throttledSync.cancel();
console.log(throttledSync.pending()); // false
// Nothing syncs at t=2000

// Option 2: Flush - execute immediately
throttledSync({ v: 4 }); // Executes immediately
throttledSync({ v: 5 }); // Queued
throttledSync.flush();   // Immediately logs: "Syncing: {"v":5}"

// React cleanup pattern
useEffect(() => {
  const throttled = throttle(handleScroll, 100);
  window.addEventListener("scroll", throttled);
  
  return () => {
    throttled.flush(); // Ensure final state is captured
    throttled.cancel(); // Then cleanup
    window.removeEventListener("scroll", throttled);
  };
}, []);

Implementation Considerations

  • flush() should be idempotent if nothing is pending
  • cancel() should not affect the next leading call
  • Methods should be safely callable at any time

Follow-up Questions

  1. Should flush() return the result of the function call?
  2. How do you handle the case where flush() is called during execution?

Sample Test Cases

Case 1
Input
{"delay": 1000, "calls": [0, 100], "cancelAt": 500}
Expected Output
[0]
Case 2
Input
["func", 200]
Expected Output
["leading", "trailing_cancel", "pending_false"]
Case 3
Input
{"delay": 500, "calls": [0, 100], "flushAt": 200}
Expected Output
[0,200]
Case 4
Input
["func", 200]
Expected Output
["leading", "trailing_flush", "pending_false"]
Case 5
Input
["func", 200]
Expected Output
["leading", "trailing_wait", "pending_false"]
Case 6
Input
[
  "const results = [];\n  const func = (val) => results.push(val);\n  const throttled = throttle(func, 100);\n\n  throttled(1); // Leading call\n  throttled(2); // Queued\n  throttled.cancel(); // Cancel pending\n\n  setTimeout(() => {\n    throttled(3); // New leading call after cancel\n    throttled(4); // Queued\n  }, 150);\n\n  setTimeout(() => {\n    throttled.flush(); // Flush pending\n  }, 300);\n\n  setTimeout(() => {\n    return results;\n  }, 400);
]
Expected Output
[1, 3, 4]
Case 7
Input
[
  "const results = [];\n  const func = (val) => results.push(val);\n  const throttled = throttle(func, 100);\n\n  throttled(1); // Leading\n  throttled(2); // Queued\n  throttled(3); // Replaces 2\n\n  setTimeout(() => {\n    throttled.flush(); // Flush 3\n    throttled.flush(); // Idempotent call\n  }, 150);\n\n  setTimeout(() => {\n    return results;\n  }, 200);
]
Expected Output
[1, 3]
Case 8
Input
[
  "const results = [];\n  const func = (val) => results.push(val);\n  const throttled = throttle(func, 100);\n\n  throttled(1); // Leading\n  throttled(2); // Queued\n\n  setTimeout(() => {\n    throttled.cancel(); // Cancel 2\n    throttled.cancel(); // Idempotent call\n  }, 50);\n\n  setTimeout(() => {\n    return results;\n  }, 200);
]
Expected Output
[1]

No solutions yet

Be the first to share a solution for this question.

Comments (0)

Sign in to leave a comment.

No comments yet. Be the first to comment.

Stats

Views
51
Likes
0
Solutions
0
Comments
0

Category

Frontend Engineering