Victor
Victor

Reputation: 89

Node.js Control Flow and Callbacks

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

Upvotes: 1

Views: 5702

Answers (3)

Patrick Motard
Patrick Motard

Reputation: 2660

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.

Upvotes: 2

Harekam Singh
Harekam Singh

Reputation: 66

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.

Upvotes: 0

Paul
Paul

Reputation: 141829

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);

Upvotes: 0

Related Questions