Skip to content

Commit

Permalink
timers: allow passing delay to timer.refresh()
Browse files Browse the repository at this point in the history
  • Loading branch information
mscdex committed Apr 26, 2022
1 parent d8460de commit efff092
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 16 deletions.
2 changes: 1 addition & 1 deletion doc/api/deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -3234,7 +3234,7 @@ Convert them to primitive strings.
[`setTimeout()`]: timers.md#settimeoutcallback-delay-args
[`socket.bufferSize`]: net.md#socketbuffersize
[`timeout.ref()`]: timers.md#timeoutref
[`timeout.refresh()`]: timers.md#timeoutrefresh
[`timeout.refresh()`]: timers.md#timeoutrefreshdelay-resetinterval
[`timeout.unref()`]: timers.md#timeoutunref
[`tls.CryptoStream`]: tls.md#class-tlscryptostream
[`tls.SecureContext`]: tls.md#tlscreatesecurecontextoptions
Expand Down
16 changes: 12 additions & 4 deletions doc/api/timers.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,26 @@ When called, requests that the Node.js event loop _not_ exit so long as the
By default, all `Timeout` objects are "ref'ed", making it normally unnecessary
to call `timeout.ref()` unless `timeout.unref()` had been called previously.

### `timeout.refresh()`
### `timeout.refresh([delay[, resetInterval]])`

<!-- YAML
added: v10.2.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/40434
description: Added `delay` and `resetInterval` parameters.
-->

* `delay` {number} The number of milliseconds to wait before calling the
original callback.
* `resetInterval` {boolean} For an interval timer, should the interval be set to
`delay`? **Default:** `false`.
* Returns: {Timeout} a reference to `timeout`

Sets the timer's start time to the current time, and reschedules the timer to
call its callback at the previously specified duration adjusted to the current
time. This is useful for refreshing a timer without allocating a new
JavaScript object.
call its callback at the previously specified duration or the duration specified
by `delay` adjusted to the current time. This is useful for refreshing a timer
without allocating a new JavaScript object.

Using this on a timer that has already called its callback will reactivate the
timer.
Expand Down
34 changes: 23 additions & 11 deletions lib/internal/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,20 +158,25 @@ function initAsyncResource(resource, type) {
if (initHooksExist())
emitInit(asyncId, type, triggerAsyncId, resource);
}
function calcAfter(after) {
after *= 1; // Coalesce to number or NaN
if (!(after >= 1 && after <= TIMEOUT_MAX)) {
if (after > TIMEOUT_MAX) {
process.emitWarning(`${after} does not fit into` +
' a 32-bit signed integer.' +
'\nTimeout duration was set to 1.',
'TimeoutOverflowWarning');
}
after = 1; // Schedule on next tick, follows browser behavior
}
return after;
}

class Timeout {
// Timer constructor function.
// The entire prototype is defined in lib/timers.js
constructor(callback, after, args, isRepeat, isRefed) {
after *= 1; // Coalesce to number or NaN
if (!(after >= 1 && after <= TIMEOUT_MAX)) {
if (after > TIMEOUT_MAX) {
process.emitWarning(`${after} does not fit into` +
' a 32-bit signed integer.' +
'\nTimeout duration was set to 1.',
'TimeoutOverflowWarning');
}
after = 1; // Schedule on next tick, follows browser behavior
}
after = calcAfter(after);

this._idleTimeout = after;
this._idlePrev = this;
Expand Down Expand Up @@ -204,7 +209,14 @@ class Timeout {
});
}

refresh() {
refresh(after, resetInterval) {
if (after !== undefined) {
after = calcAfter(after);
this._idleTimeout = after;
if (this._repeat !== null && resetInterval)
this._repeat = after;
}

if (this[kRefed])
active(this);
else
Expand Down
31 changes: 31 additions & 0 deletions test/sequential/test-timers-refresh-args.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict';
require('../common');
const assert = require('assert');

const LONGER_DELAY = 1000;
const SHORTER_DELAY = 100;
let last;
let t = setTimeout(() => {
if (last !== undefined) {
assert(Date.now() - last < LONGER_DELAY);

last = undefined;
let count = 0;
t = setInterval(() => {
if (last !== undefined)
assert(Date.now() - last < LONGER_DELAY);
last = Date.now();
switch (count++) {
case 0:
t.refresh(SHORTER_DELAY, true);
break;
case 3:
clearInterval(t);
break;
}
}, LONGER_DELAY);
return;
}
last = Date.now();
t.refresh(SHORTER_DELAY);
}, LONGER_DELAY);

0 comments on commit efff092

Please sign in to comment.