Skip to content

feat(async/unstable): allow setting dynamic timeframe for throttle#7002

Merged
kt3k merged 7 commits intodenoland:mainfrom
lionel-rowe:throttle-dynamic
Mar 6, 2026
Merged

feat(async/unstable): allow setting dynamic timeframe for throttle#7002
kt3k merged 7 commits intodenoland:mainfrom
lionel-rowe:throttle-dynamic

Conversation

@lionel-rowe
Copy link
Contributor

@lionel-rowe lionel-rowe commented Feb 13, 2026

Closes #6796.

If fn returns a promise, lastExecution is now based on the asynchronous end time of the previous completed call. For example with this function:

async function fn() {
    const start = performance.now()
    while (performance.now() - start < 50) { /* idle  loop */ }
    await new Promise((res) => setTimeout(res, 100))
}

If the throttled function is called once at time 0 and we observe lastExecution:

Observation time Current implementation New implementation
0 -Infinity -Infinity
100 ~50 -Infinity
200 ~50 ~150

This will also affect how throttling works with asynchronous functions — the current implementation basically doesn't throttle at all for typical async functions, whereas the new one does.

@lionel-rowe lionel-rowe requested a review from kt3k as a code owner February 13, 2026 01:05
@github-actions github-actions bot added the async label Feb 13, 2026
@lionel-rowe lionel-rowe changed the title feat(async/unstable): allow setting dynamic timeframe for throttle feat(async/unstable): allow setting dynamic timeframe for throttle Feb 13, 2026
@lionel-rowe lionel-rowe marked this pull request as draft February 13, 2026 01:22
@codecov
Copy link

codecov bot commented Feb 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.71%. Comparing base (823ee48) to head (2baf7d9).
⚠️ Report is 33 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7002      +/-   ##
==========================================
- Coverage   94.21%   93.71%   -0.51%     
==========================================
  Files         615      620       +5     
  Lines       47840    49423    +1583     
  Branches     8320     8660     +340     
==========================================
+ Hits        45074    46315    +1241     
+ Misses       2699     2516     -183     
- Partials       67      592     +525     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@lionel-rowe lionel-rowe marked this pull request as ready for review February 13, 2026 17:09
*/
// deno-lint-ignore no-explicit-any
export function throttle<T extends Array<any>>(
fn: (this: ThrottledFunction<T>, ...args: T) => void,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return type of the function should be updated to match the new async handling, something like void | PromiseLike<void>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that but actually returning a promise doesn't really make sense, as the wrapped function doesn't always run and so the return value should be treated as meaningless and discarded, i.e. should be void/undefined.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, the return value is discarded. So I guess the benefit of adding PromiseLike is to signal/document fn?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, the return value is discarded. So I guess the benefit of adding PromiseLike is to signal/document fn?

Sorry, I don't follow. PromiseLike is not part of the signature, but promise-likes do now have special handling to enable lastExecution to track their time-to-resolve rather than time-to-sync-return.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I don't follow. PromiseLike is not part of the signature, but promise-likes do now have special handling to enable lastExecution to track their time-to-resolve rather than time-to-sync-return.

It was more of a cosmetic thing. Totally fine to keep it like this ☺️

@kt3k
Copy link
Member

kt3k commented Feb 16, 2026

@lionel-rowe Can you also add an example with comment about when to use the new option?

Copy link
Member

@kt3k kt3k left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@kt3k kt3k merged commit 25aa81f into denoland:main Mar 6, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@std/async throttle dynamically adjusted timeframe

3 participants