How to prevent Node.js from exiting while waiting for a callback?

I have a code like this:

var client = new mysql.Client(options); console.log('Icanhasclient'); client.connect(function (err) { console.log('jannn'); active_db = client; console.log(err); console.log('hest'); if (callback) { if (err) { callback(err, null); } callback(null, active_db); } }); 

My problem is that Node exits right after launch. It prints "Icanhasclient", but not one of console.log inside the callback is called.

(mysql in this example node-mysql .

Is there anything that can be done to make node.js wait for the callback to complete before exiting?

+82
Jun 22 '11 at 15:43
source share
8 answers

Callback not in queue

Node is executed until all queue events are empty. The callback is added to the event queue. when call for example

  emmiter1.on('this_event',callback). 

done. This call is part of the code written by the module developer.

If the module is a fast port from the synchronous / blocking version, this may not happen until any part of the operation is completed, and all queues may be omitted before this happens, which allows the node to exit silently.

This is an impenetrable error, that is, one that the module developer may not run during development, since this will happen less often in busy systems with many queues , since it will be rare for all of them to be empty at a critical moment.

A possible error / error detector for the user is to insert a special timer event before calling a suspicious function.

+47
Dec 26 '11 at 12:59
source share

You can simply issue setTimeout or a repeating timeout with setInterval.

If you want to check the exit conditions, you can also do a conditional timeout:

 (function wait () { if (!SOME_EXIT_CONDITION) setTimeout(wait, 1000); })(); 

Put this at the end of your code and the console will just wait ... and wait ... until you want to close it.

+37
Apr 29 '14 at 1:40
source share

My solution was to instantiate an EventEmitter and listen to my custom event.

 var eventEmitter = new process.EventEmitter(); 

then I called eventEmitter.emit from the asynchronous callback:

 client.connect(function (err) { eventEmitter.emit('myevent', {something: "Bla"}) }); 

The last thing in my script was eventEmitter.on :

 eventEmitter.on('myevent', function(myResult){ // I needed the result to be written to stdout so that the calling process could get it process.stdout.write(JSON.stringify(myResult)); }); 

Node will wait for the event handler to complete.

+11
Jul 20 '17 at 21:53 on
source share

Based on @Todd's answer, I created a one-liner. Include it at the beginning of your script and set done = true when you are done:

 var done = (function wait () { if (!done) setTimeout(wait, 1000) })(); 

Example:

 var done = (function wait () { if (!done) setTimeout(wait, 1000) })(); someAsyncOperation().then(() => { console.log('Good to go!'); done = true; }); 

How it works? If we expand it a bit:

 // Initialize the variable 'done' to 'undefined' // Create the function wait, which is available inside itself // Note: 'var' is hoisted but 'let' is not so we need to use 'var' var done = (function wait () { // As long as it nor marked as done, create a new event+queue if (!done) setTimeout(wait, 1000); // No return value; done will resolve to false (undefined) })(); 
+2
May 21 '18 at 15:04
source share

I wonder why no one posted an answer that doesn't block at all!

 const http = require('http'); http.createServer((req, res) => { res.end(''); }).listen(3000, function() { console.log("listening on port 3000, don't expect any response :-)"); }); 

This will make Node.js wait and listen on port 3000, creating a server that does nothing (thus waiting and not blocking at all)

0
Apr 13 '19 at 6:54
source share

Here are my two cents:

 async function main() { await new Promise(function () {}); console.log('This text will never be printed'); } function panic(error) { console.error(error); process.exit(1); } // https://stackoverflow.com/a/46916601/1478566 main().catch(panic).finally(clearInterval.bind(null, setInterval(a=>a, 1E9))); 
0
Jul 28 '19 at 12:48
source share

I looked through the felixge / node-mysql library and did not see the link to the client.connect command in the API. Is this the real challenge you're trying to make (not trying to be ridiculous here)? Regardless of IMHO, you need to think more about how Javascript is developed because it uses a programming paradigm different from most other popular languages.

The first problem that I see in your code is that you did not define a callback, so it does not actually exist. I would suggest that console.log (callback) is undefined. From your code, the anonymous function is a callback for the client.connect function. You must determine that you are calling a "callback" in a higher scope. For example, I will define the myCallback function to exist in an area higher than the client.connect anonymous function. It may be useful to find Javacscript variable scope .

  var myCallback(err, response) { if (err) { console.log('err:%s',err); } else { console.log('response:%s',response); } } client.connect(err, function(response) { // this anonymous function is the callback to client.connect, the var // 'callback' would be undefined. if (err) { myCallback(err); return; // Explicit call to return, else the lines below would run. } myCallback(null, response); }); 

Secondly, if you do not explicitly call return inside Javascript, the function will continue to be processed. I was bitten by it. Finally, Javascript starts the event-driven loop because it will never wait for functions to return, so we have all these callbacks in the first place. You can make Javascript behave differently, for example, by using a while loop until the condition is true. See the “Asynchronous” caolan library for various event loop management strategies. The main disadvantage of using these methods is that you actually spend CPU cycles / blocking, when you probably should use more callbacks and just rethink how your programs work.

-one
Apr 29 2018-12-12T00:
source share

Please try this. Check if this helps.

 var client = new mysql.Client(options); console.log('Icanhasclient'); var verbose; if (!verbose) { return new Promise(function (resolve, reject) { client.connect(function (err) { if (err) { console.log(Error in connecting SQL ${err} ) ; return reject(err); } verbose = client; return resolve(verbose); }) }) } else { return new Promise(function (resolve) { resolve(verbose); }) } 
-one
Sep 12 '19 at 15:11
source share



All Articles