diff --git a/doc/api/timers.md b/doc/api/timers.md index 66ee2ca97e8455..2f53d805227d49 100644 --- a/doc/api/timers.md +++ b/doc/api/timers.md @@ -151,8 +151,9 @@ next event loop iteration. If `callback` is not a function, a [`TypeError`][] will be thrown. -This method has a custom variant for promises that is available using -[`util.promisify()`][]: +If this method is invoked as its [`util.promisify()`][]ed version, it returns a +Promise. The created `Immediate` is attached to the Promise as a `immediate` +property. ```js const util = require('util'); @@ -170,6 +171,13 @@ async function timerExample() { console.log('After I/O callbacks'); } timerExample(); + +// You can access the immediate on promise.immediate +const promise = setImmediatePromise(); +promise.then(() => { + // This callback is never called because the Immediate is cleared +}); +clearImmediate(promise.immediate); ``` ### setInterval(callback, delay[, ...args]) @@ -213,8 +221,9 @@ will be set to `1`. Non-integer delays are truncated to an integer. If `callback` is not a function, a [`TypeError`][] will be thrown. -This method has a custom variant for promises that is available using -[`util.promisify()`][]: +If this method is invoked as its [`util.promisify()`][]ed version, it returns a +Promise. The created `Timeout` is attached to the Promise as a `timeout` +property. ```js const util = require('util'); @@ -224,6 +233,12 @@ setTimeoutPromise(40, 'foobar').then((value) => { // value === 'foobar' (passing values is optional) // This is executed after about 40 milliseconds. }); + +const promise = setTimeoutPromise(40, 'foobar'); +promise.then((value) => { + // This is never executed because the timeout is cleared +}); +clearTimeout(promise.timeout); ``` ## Cancelling Timers diff --git a/lib/timers.js b/lib/timers.js index 98acbf8fa44152..09c52cc4ce7485 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -147,9 +147,11 @@ function setTimeout(callback, after, arg1, arg2, arg3) { setTimeout[customPromisify] = function(after, value) { const args = value !== undefined ? [value] : value; - return new Promise((resolve) => { - active(new Timeout(resolve, after, args, false)); - }); + let resolve; + const promise = new Promise((res) => resolve = res); + promise.timeout = new Timeout(resolve, after, args, false); + active(promise.timeout); + return promise; }; function clearTimeout(timer) { @@ -272,7 +274,10 @@ function setImmediate(callback, arg1, arg2, arg3) { } setImmediate[customPromisify] = function(value) { - return new Promise((resolve) => new Immediate(resolve, [value])); + let resolve; + const promise = new Promise((res) => resolve = res); + promise.immediate = new Immediate(resolve, [value]); + return promise; }; function clearImmediate(immediate) { diff --git a/test/parallel/test-timer-immediate-async-cleared.js b/test/parallel/test-timer-immediate-async-cleared.js new file mode 100644 index 00000000000000..5fa5323fb28c74 --- /dev/null +++ b/test/parallel/test-timer-immediate-async-cleared.js @@ -0,0 +1,10 @@ +'use strict'; +const { mustNotCall } = require('../common'); +const { promisify } = require('util'); + +const setImmediateAsync = promisify(setImmediate); + +const expected = ['foo', 'bar', 'baz']; +const promise = setImmediateAsync(...expected); +promise.then(() => mustNotCall('expected immediate to be cleared')); +clearImmediate(promise.immediate); diff --git a/test/parallel/test-timer-immediate-async.js b/test/parallel/test-timer-immediate-async.js new file mode 100644 index 00000000000000..b9891202e686cb --- /dev/null +++ b/test/parallel/test-timer-immediate-async.js @@ -0,0 +1,12 @@ +'use strict'; +require('../common'); +const { strictEqual } = require('assert'); +const { promisify } = require('util'); + +const setImmediateAsync = promisify(setImmediate); + +const expected = ['foo', 'bar', 'baz']; +// N.B. the promisified version of setImmediate will resolve with the _first_ +// value, not an array of all values. +setImmediateAsync(...expected) + .then((actual) => strictEqual(actual, expected[0])); diff --git a/test/parallel/test-timer-timeout-async-cleared.js b/test/parallel/test-timer-timeout-async-cleared.js new file mode 100644 index 00000000000000..043181cb3ffecc --- /dev/null +++ b/test/parallel/test-timer-timeout-async-cleared.js @@ -0,0 +1,10 @@ +'use strict'; +const { mustNotCall } = require('../common'); +const { promisify } = require('util'); + +const setTimeoutAsync = promisify(setTimeout); + +const expected = ['foo', 'bar', 'baz']; +const promise = setTimeoutAsync(10, ...expected); +promise.then(() => mustNotCall('expected timeout to be cleared')); +clearTimeout(promise.timeout); diff --git a/test/parallel/test-timer-timeout-async.js b/test/parallel/test-timer-timeout-async.js new file mode 100644 index 00000000000000..618713bc93e44b --- /dev/null +++ b/test/parallel/test-timer-timeout-async.js @@ -0,0 +1,12 @@ +'use strict'; +require('../common'); +const { strictEqual } = require('assert'); +const { promisify } = require('util'); + +const setTimeoutAsync = promisify(setTimeout); + +const expected = ['foo', 'bar', 'baz']; +// N.B. the promisified version of setTimeout will resolve with the _first_ +// value, not an array of all values. +setTimeoutAsync(10, ...expected) + .then((actual) => strictEqual(actual, expected[0]));