2
function placeOrder(orderNo) {
console.log("Order is: " + orderNo);

setTimeout(deliver(orderNo),5000);
}

function deliver(orderNo) {
    console.log("Item is delivered with Order No.- " + orderNo);
}

placeOrder(1);
placeOrder(2);
placeOrder(3);
placeOrder(4);
placeOrder(5);
placeOrder(6);

The above code is a nodejs code whose output should be:

order No:1
order No:2
order No:3
order No:4
order No:5
order No:6
Item is delivered with order No.- 1
Item is delivered with order No.- 2
Item is delivered with order No.- 3
Item is delivered with order No.- 4
Item is delivered with order No.- 5
Item is delivered with order No.- 6

But i am getting an output like this:

order No:1
Item is delivered with order No.- 1
order No:2
Item is delivered with order No.- 2
order No:3
Item is delivered with order No.- 3
order No:4
Item is delivered with order No.- 4
order No:5
Item is delivered with order No.- 5
order No:6
Item is delivered with order No.- 6

I am going wrong somewhere in my concept of single thread and asynchronous callbacks. Please someone explain me how the code is working.

Neil
  • 59
  • 1
  • 7

3 Answers3

2

Replace:

setTimeout(deliver(orderNo),5000);
}

with:

setTimeout(function() {
    deliver(orderNo); 
}, 5000);

The first parameter of the setTimeout function is a function pointer. In your code you were passing the result of the deliver(orderNo) call which is just some void parameter. Now you can get rid of the console.log inside your placeOrder function.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
2

You use wrong setTimeout signature definition

var timeoutID = window.setTimeout(func, [delay, param1, param2, ...]);
var timeoutID = window.setTimeout(code, [delay]);

Hence, your code should be:

setTimeout(function() {
  deliver(orderNo);
}, 5000);
babygau
  • 1,551
  • 18
  • 27
0

tl;dr

This is a syntax issue. You are passing in the wrong argument type to setTimeout.

Change this:

setTimeout(deliver(orderNo),5000);

to this:

setTimeout(deliver, 5000, orderNo);

Be wary that this syntax does not work in IE 9 or below.

Explanation

If you look at the documentation for setTimeout on MDN, you will see that the first argument is either a Function or a String consisting of JavaScript code. In your case, you are trying to pass in a function which accepts this syntax:

setTimeout(func, [delay, param1, param2, ...]);

Where param1, param2, ... are the arguments for your function, func. What you are doing is passing in the value returned by the function rather than the function itself.

Since you are passing a value, setTimeout does not execute as expected. The reason you are still getting an output from deliver is because it is actually being executed at runtime rather than by setTimeout. It's almost the same thing as calling deliver by itself.

Functions as Arguments

Remember that functions are First-Class Citizens in JavaScript, which means they can be passed into function as arguments.

Bonus

There are a few alternative syntaxes you can use.

String

As pokeybit mentioned in the comments:

setTimeout("deliver("+orderNo+");",5000);

Which allows you to use the function and it's parameters at once. However, this is an uglier syntax due to the string concatenation.

Anonymous Function

Use setTimeout with an anonymous function:

setTimeout(function() {
  console.log("Item is delivered with Order No.- " + orderNo);
}, 5000);

This is arguably the most common and safest syntax.

Function that returns an anonymous function

You can keep:

setTimeout(deliver(orderNo),5000);

If you define deliver as a function that returns a Function:

function deliver(orderNo) {
  return function() {
    console.log("Item is delivered with Order No.- " + orderNo);
  }
}

Since this value returns a function, it is the proper type for setTimeout.

Community
  • 1
  • 1
Pori
  • 696
  • 3
  • 7
  • 18