1

I've been confused on this for a month and searched everything but could not find an answer.

I want to get control of what runs first in the node.js. I know the way node deals with the code is non-blocking. I have the following example:

setTimeOut(function(){console.log("one second passed");}, 1000);
console.log("HelloWorld");    

Here I want to run first one, output "one second passed", and then run the second one. How can I do that? I know setTimeOut is a way to solve this problem but that's not the answer I am looking for. I've tried using callback but not working. I am not sure about if I got the correct understanding of callbacks. Callbacks just mean function parameters to me and I don't think that will help me to solve this problem.

One possible way to solve this problem is to define a function that contains the "error first callback" like the following example:

function print_helloworld_atend(function helloworld(){
    console.log("HelloWorld");
}){
    setTimeOut(function(){console.log("one second passed");}, 1000);
    helloworld();
}    

Can I define a function with a callback who will know when the previous tasks are done. In the above function, how to make the callback function: helloworld to run after the "setTimeOut" expression?

If there is a structure that can solve my problem, that's my first choice. I am tired of using setTimeOuts.

I would really appreciate if anyone can help. Thanks for reading

Victor
  • 79
  • 3
  • 8

3 Answers3

2

You should be using promises. Bluebird is a great promise library. Faster than native and comes with great features. With promises you can chain together functions, and know that one will not be called until the previous function resolves. No need to set timeouts or delays. Although you can if you'd like. Below is example of a delay. Function B wont run until 6 seconds after A finishes. If you remove .delay(ms) B will run immediately after A finishes.

var Promise = require("bluebird");
console.time('tracked');
console.time('first');
function a (){
    console.log('hello');
    console.timeEnd('first');
    return Promise.resolve();
}
function b (){
    console.log('world');
    console.timeEnd('tracked');
}


a().delay(6000)
    .then(b)
    .catch(Promise.TimeoutError, function(e) {
        console.log('Something messed up yo', e);
    });

This outputs:

→ node test.js
hello
first: 1.278ms
world
tracked: 6009.422ms

Edit: Promises are, in my opinion, the most fun way of control flow in node/javascript. To my knowledge there is not a .delay() or .timeout() in native javascript promises. However, there are Promises in general. You can find their documentation on mozilla's site. I would recommend that you use Bluebird instead though.

Use bluebird instead of native because:

  • It's faster. Petka Antonov, the creator of bluebird, has a great understanding of the V8 engines two compile steps and has optimized the library around it's many quirks. Native has little to no optimization and it shows when you compare their performance. More information here and here.

  • It has more features: Nice things like .reflect(), .spread(), .delay(), .timeout(), the list goes on.

  • You lose nothing by switching: all features in bluebird which also exist in native function in exactly the same way in implementation. If you find yourself in a situation where only native is available to you, you wont have to relearn what you already know.

Community
  • 1
  • 1
Patrick Motard
  • 2,650
  • 2
  • 14
  • 23
0

Just execute everything that you want to execute after you log "one second passed", after you log "one second passed":

setTimeOut(function(){
    console.log("one second passed");
    console.log("HelloWorld");
}, 1000);
Paul
  • 139,544
  • 27
  • 275
  • 264
  • Hi, thank you for replying. The above is just an example. I know this would fix but I got tons of code, functions and modules and I can not calculate time for each of them. Do you have another way that can make it happen? – Victor Aug 26 '16 at 20:22
  • @Victor You don't need to calculate any time, just put your code after the code you want it to run after, but not outside the `setTimeout` or whichever other function you call that has some delay. Keep everything that you want to happen after the timeout inside the callback for that timeout. – Paul Aug 26 '16 at 20:26
  • @Victor You can use [Promise](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)s to organize the code a bit nicer, which I highly recommend, but Promise's don't add any functionality that you can't already achieve using callbacks and I think it is important to understand callbacks and how you would make your own Promise before you use Promises. – Paul Aug 26 '16 at 20:28
  • the line of code inside settimeout is just an example that means a lot of work to be done. And my question is how I can know when the process is done. thanks – Victor Aug 26 '16 at 20:58
  • @Victor Everything inside the callback executes after its done. – Paul Aug 26 '16 at 21:18
  • why? just look at my post above. inside the second piece of code. the helloworld is a callback function but it actually run first – Victor Aug 26 '16 at 21:30
  • @Victor You are running it first. You need to run it inside the callback for it to run after: `setTimeout(function(){console.log("one second passed"); helloworld(); }, 1000);` – Paul Aug 26 '16 at 21:31
  • Yes, I know what you mean. But that is for the callback function defined by the function setTimeout. For the setTimeout, I know there is a callback that can handle something once the previous jobs were done. But how to define this kind of callback function inside my self-defined function? In the same example I gave you. How to let the helloworld function know when the previous settimeout has been fully executed? – Victor Aug 26 '16 at 21:50
  • @Victor You can't. You don't need to either, you can run it inside the callback for the `setTimeout` and then it will run when you want it to. That satisifies your requirements. There is more info about a similar problem here: http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – Paul Aug 26 '16 at 21:53
0

You can use async module to handle the callbacks.

To understand callbacks I'll give you a high level glance:

function: i want to do some i/o work.
nodejs: ok, but you shouldn't be blocking my process as I'm single threaded.
nodejs: pass a callback function, and I will let you know from it when the i/o work is done. function: passes the callback function
nodejs: i/o work is done, calls the callback function.
function: thanks for the notification, continue processing other work.

  • The problem is I don't know when the work is done and how I can ask my callback function to monitor the process and execute when the process is done – Victor Aug 26 '16 at 20:56