Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created July 12, 2017 12:31
Show Gist options
  • Select an option

  • Save bennadel/998aa3f30e50e88b5311f49dad3e0831 to your computer and use it in GitHub Desktop.

Select an option

Save bennadel/998aa3f30e50e88b5311f49dad3e0831 to your computer and use it in GitHub Desktop.
Calling Timeout.unref() With setTimeout() Does Not Appear To Be A Best Practice In Node.js
// Require the application modules.
var api = require( "./api" );
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
var TEN_SECONDS = ( 10 * 1000 );
function runWithTimeout( command, timeout = TEN_SECONDS ) {
// Since we can't cancel a command once it has been executed, we have to
// conditionally turn a command into either a resolved or a rejected promise. In
// this case, we'll use a timer to generate a rejected promise prior to command
// completion if the command takes too long to return.
var promise = new Promise(
function( resolve, reject ) {
// Setup our rejection timer to preemptively kill hanging commands.
var timer = setTimeout(
function rejectHangingCommand() {
reject( new Error( "Command took too long (and was timed-out)." ) );
},
timeout
);
// ************************************************************** //
// ************************************************************** //
// CAUTION: This is the line that seemingly makes no sense (to me).
// I cannot figure out what purpose it actually serves.
timer.unref();
// ************************************************************** //
// ************************************************************** //
// Catch any synchronous execution errors.
try {
var commandPromise = Promise.resolve( command() );
} catch ( error ) {
var commandPromise = Promise.reject( error );
}
// Once the command returns, we need to use the result to fulfill the
// contextual Promise. However, the command may return before OR after the
// timeout has already rejected the contextual Promise. As such, the
// following operations may actually be No-Op instructions.
commandPromise.then(
function handleResolve( result ) {
clearTimeout( timer );
resolve( result );
},
function handleReject( error ) {
clearTimeout( timer );
reject( error );
}
);
}
);
return( promise );
}
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
// Run the command with a 1-Second timeout. Since our command will take 5-Seconds to
// execute, we know that the command-runner's timer will terminate the request early.
var promise = runWithTimeout(
function command() {
return( api.echoAfterTimeout( "[data payload]", 5000 ) );
},
1000
);
promise.then(
function handleResolve( result ) {
console.log( "Success:", result );
},
function handleReject( error ) {
console.log( "Error:", error );
}
);
console.log( "App started." );
var timer = setTimeout(
function timeoutCallback() {
console.log( "Timer callback." );
},
1000
);
// At this point, the timer is the only action that would hold the node-process open. By
// unref-ing it, the process will exit prior to the timeout callback execution and we
// should never see the second console.log() statement.
timer.unref();
@khaled4vokalz

khaled4vokalz commented May 22, 2025 •

Copy link
Copy Markdown

// CAUTION: This is the line that seemingly makes no sense (to me).
// I cannot figure out what purpose it actually serves.

I guess you've already figured that out, nevertheless, I think you can think of a scenario like this.

      const myTimeout = setTimeout(() => {
        // if the process is still running after 5 seconds, we can forcefully kill it
        process.exit(1);
      }, 5000);
        // we're unrefing it so that, if node's event loop becomes empty before 5 seconds it exits gracefully and we're not blocking that
      myTimeout.unref();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment