WristMan
WristMan

Reputation: 347

How to make a NodeJs function wait?

For example I have these two functions:

var count= function(){
    for(i=1;i<=3;i++){
        console.log(i);
    }
    setTimeout(function(){
        for(i=1;i<=3;i++){
            console.log(-i);
         }
    },2000);
} 

var letters = function(){
     var charSet = 'abcdefghijklmnopqrstuvvwxyz'
     for(i=0;i<3;i++){
         console.log(charSet[i]);
     }
}

When I execute them in this order:

count();
letters();

I expect to get as output:

1 2 3 -1 -2 -3 a b c

But what I get is:

1 2 3 a b c -1 -2 -3

Why the function does not wait the Timeout to finish? How can I achieve the desired behaviour?

Upvotes: 2

Views: 875

Answers (3)

Mike Cluck
Mike Cluck

Reputation: 32511

Why the function does not wait the Timeout to finish?

Because that's not how setTimeout works.

What actually happens is you put in a request to have your function run in no less than X milliseconds (2000 in your case). The JS runtime will wait for all other code to finish running then see if it's been at least X milliseconds. Once it has, your function will run. But in the meantime, you can run any other JS code. It intentionally doesn't block other code from running.

How can I achieve the desired behaviour?

The best answer is structure your code differently. You need to learn to work with asynchronous events. The simplest way would be to use a callback function:

var count = function(cb) {
  for (i = 1; i <= 3; i++) {
    console.log(i);
  }
  setTimeout(function() {
    for (i = 1; i <= 3; i++) {
      console.log(-i);
    }
    
    // Run the function we passed to it after the rest is done
    cb();
  }, 2000);
}

var letters = function() {
  var charSet = 'abcdefghijklmnopqrstuvvwxyz'
  for (i = 0; i < 3; i++) {
    console.log(charSet[i]);
  }
}

count(letters); // Pass `letters` as a callback so it will be called after `count` is done

Upvotes: 2

Patrick Bell
Patrick Bell

Reputation: 769

The reason that you aren't getting 1 2 3 -1 -2 -3 a b c is because your code does not stop at the setTimeout(...) call. This is because many JavaScript methods, by nature, are asynchronous. This means that they will not stop the flow of your code. That means when you call setTimeout(...), the JavaScript interpreter will make sure that the function passed into setTimeout is run in 2000ms, but does not stop and wait for it. It will continue on its normal execution flow, onto the next instruction.

If you wanted it to wait, you could put the letters() call after you print out the remaining numbers (-1, -2, -3).

    setTimeout(function(){
        for(i=1;i<=3;i++){
            console.log(-i);
         }
         letters();
    },2000);

Upvotes: 2

OrangeDog
OrangeDog

Reputation: 38816

Because setTimeout schedules the second loop to run later (in ~2 seconds), then returns immediately.

Node.js is for asynchronous, event-driven programming. You do not want to be blocking execution at all - the behaviour you are asking for is not "desired" at all.

I suggest you read up about Node.js and asynchronous programming, then re-visit what it is you are actually trying to do. You probably want something more like this:

function count(callback) {
    for (i=1; i<=3; i++){
        console.log(i);
    }
    setTimeout(function() {
        for(i=1;i<=3;i++){
            console.log(-i);
        }
        callback();
    }, 2000);
} 

function letters() {
     var charSet = 'abcdefghijklmnopqrstuvvwxyz'
     for (i=0; i<3; i++){
         console.log(charSet[i]);
     }
}

And run it like:

count(letters);

Upvotes: 1

Related Questions