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.

2
  • 1
    Change to; setTimeout("deliver("+orderNo+");",5000); Commented Nov 29, 2015 at 14:09
  • 1
    also, please indent your code ;) Commented Nov 29, 2015 at 15:11

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

Comments

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

Comments

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.

1 Comment

No problem. We've all fallen for the setTimeout gotcha at one point or another.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.