From 18ddfd5c4a5c7d7ffe90e4acc92f0160558d1e77 Mon Sep 17 00:00:00 2001 From: Brian White Date: Tue, 12 Oct 2021 19:06:34 -0400 Subject: [PATCH] timers: allow passing delay to timer.refresh() --- doc/api/deprecations.md | 2 +- doc/api/timers.md | 16 +++++++++--- lib/internal/timers.js | 20 +++++++++++--- test/sequential/test-timers-refresh-args.js | 29 +++++++++++++++++++++ 4 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 test/sequential/test-timers-refresh-args.js diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index ef73392a52b74d..f8684cfbdf772c 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -2952,7 +2952,7 @@ it was an aborted or graceful destroy. [`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 diff --git a/doc/api/timers.md b/doc/api/timers.md index 9105e93a9a6bb3..1910a33f4e44d9 100644 --- a/doc/api/timers.md +++ b/doc/api/timers.md @@ -105,17 +105,25 @@ 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]])` +* `delay` {number} The number of milliseconds to wait before calling the + original callback. **Default:** `1`. +* `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. diff --git a/lib/internal/timers.js b/lib/internal/timers.js index 9a07fe3348f65e..d50230ae608796 100644 --- a/lib/internal/timers.js +++ b/lib/internal/timers.js @@ -162,9 +162,7 @@ function initAsyncResource(resource, type) { emitInit(asyncId, type, triggerAsyncId, resource); } -// Timer constructor function. -// The entire prototype is defined in lib/timers.js -function Timeout(callback, after, args, isRepeat, isRefed) { +function calcAfter(after) { after *= 1; // Coalesce to number or NaN if (!(after >= 1 && after <= TIMEOUT_MAX)) { if (after > TIMEOUT_MAX) { @@ -175,6 +173,13 @@ function Timeout(callback, after, args, isRepeat, isRefed) { } after = 1; // Schedule on next tick, follows browser behavior } + return after; +} + +// Timer constructor function. +// The entire prototype is defined in lib/timers.js +function Timeout(callback, after, args, isRepeat, isRefed) { + after = calcAfter(after); this._idleTimeout = after; this._idlePrev = this; @@ -207,7 +212,14 @@ Timeout.prototype[inspect.custom] = function(_, options) { }); }; -Timeout.prototype.refresh = function() { +Timeout.prototype.refresh = function(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 diff --git a/test/sequential/test-timers-refresh-args.js b/test/sequential/test-timers-refresh-args.js new file mode 100644 index 00000000000000..a757d35924ba6b --- /dev/null +++ b/test/sequential/test-timers-refresh-args.js @@ -0,0 +1,29 @@ +'use strict'; +require('../common'); +const assert = require('assert'); + +let last; +let t = setTimeout(() => { + if (last !== undefined) { + assert(Date.now() - last < 200); + + last = undefined; + let count = 0; + t = setInterval(() => { + if (last !== undefined) + assert(Date.now() - last < 200); + last = Date.now(); + switch (count++) { + case 0: + t.refresh(100, true); + break; + case 3: + clearInterval(t); + break; + } + }, 200); + return; + } + last = Date.now(); + t.refresh(100); +}, 200);