Design Cancellable Function - Problem

Sometimes you have a long running task, and you may wish to cancel it before it completes. To help with this goal, write a function cancellable that accepts a generator object and returns an array of two values: a cancel function and a promise.

You may assume the generator function will only yield promises. It is your function's responsibility to pass the values resolved by the promise back to the generator. If the promise rejects, your function should throw that error back to the generator.

If the cancel callback is called before the generator is done, your function should throw an error back to the generator. That error should be the string "Cancelled" (Not an Error object). If the error was caught, the returned promise should resolve with the next value that was yielded or returned. Otherwise, the promise should reject with the thrown error. No more code should be executed.

When the generator is done, the promise your function returned should resolve the value the generator returned. If, however, the generator throws an error, the returned promise should reject with the error.

Input & Output

Example 1 — Cancellation Before Completion
$ Input: function* tasks() { const val = yield new Promise(resolve => resolve(2 + 2)); yield new Promise(resolve => setTimeout(resolve, 100)); return val + 1; }
Output: Promise rejects with "Cancelled"
💡 Note: Cancel is called at 50ms, before the 100ms timeout completes. The generator receives 'Cancelled' error and the promise rejects.
Example 2 — Normal Completion
$ Input: function* tasks() { const val = yield new Promise(resolve => resolve(3)); return val * 2; }
Output: Promise resolves with 6
💡 Note: No cancellation occurs, generator completes normally: 3 * 2 = 6
Example 3 — Caught Cancellation
$ Input: function* tasks() { try { yield new Promise(resolve => setTimeout(resolve, 100)); } catch { return 'caught'; } }
Output: Promise resolves with 'caught'
💡 Note: Cancellation error is caught by try-catch block, returns 'caught' instead of rejecting

Constraints

  • The generator function will only yield promises
  • Cancellation error must be the string "Cancelled"
  • Function must handle both caught and uncaught cancellation errors
  • Promise resolution must match generator completion state

Visualization

Tap to expand
Design Cancellable Function Cooperative Cancellation with Error Propagation INPUT function* tasks() yield Promise(2+2) resolves to 4 yield setTimeout(100ms) CANCELLED HERE return val + 1 cancel() Called during 100ms wait Promise Returned to caller Returns: [cancel, promise] [Function, Promise] ALGORITHM STEPS 1 Start Generator Call gen.next() to begin 2 Await First Promise Promise resolves to 4 3 Await Second Promise setTimeout 100ms starts 4 CANCEL Called! Throw "Cancelled" to gen Error Propagation Flow cancel() gen.throw(err) Not caught in generator Promise rejects "Cancelled" FINAL RESULT Promise REJECTED Rejection Reason: "Cancelled" Why Rejection? 1. cancel() was called 2. Generator threw "Cancelled" 3. Error was NOT caught 4. Promise rejected with error val+1 never executed Key Insight: Cooperative Cancellation Pattern The cancellable() function wraps a generator and enables graceful cancellation by throwing a "Cancelled" string into the generator. If the generator doesn't catch this error, the returned promise rejects. This pattern allows long-running async operations to be interrupted while giving the generator a chance to handle cleanup. TutorialsPoint - Design Cancellable Function | Cooperative Cancellation with Error Propagation
Asked in
Google 25 Facebook 20 Amazon 15 Netflix 12
12.0K Views
Medium Frequency
~35 min Avg. Time
450 Likes
Ln 1, Col 1
Smart Actions
💡 Explanation
AI Ready
💡 Suggestion Tab to accept Esc to dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen