0

I want to get 1 3 2 output for this code, with and without usign promises.

let data = 1;
console.log(data);

data = 2;
setTimeout((data) => {
  console.log(data);
}, 2000);

data = 3;
console.log(data);

let data = 1;
console.log(data);

data = 2;
setTimeout((data) => {
  console.log(data);
}, 2000,data);

data = 3;
console.log(data);

this code gives output 1 3 2, as expected, but

console.log(data);

data = 2;
setTimeout(() => {   // argument removed from callback function
  console.log(data);
}, 2000,data);

data = 3;
console.log(data);

this code is giving output 1 3 3, but why? Why this callback function is not using data agrument passed in setTimeout.

I also used promise but still getting the 1 3 3 as output.

let data=1;
console.log(data);

data=2;
temp=new Promise((resolve, reject)=>{
    // async code
    setTimeout(()=>{
      resolve(data);
    },2000);

})

temp.then((temp)=>{
    console.log(temp);
    }).catch((err)=>{console.log(err);}
);

data=3;
console.log(data);
  • Something like https://stackoverflow.com/a/2663657/5267751 – user202729 May 10 '23 at 06:05
  • "*Why this callback function is not using data agrument passed in setTimeout.*" because the function doesn't have a parameter, thus inside the callback `console.log(data)` simply uses `data` from the outside. There is no logical reason for it to use the value of `data` passed to `setTimeout`. In essence, you're just doing `let data; setTimeout(() => console.log(data), 1000, 2); data = 3;` – VLAZ May 10 '23 at 06:07
  • basically, not different to having `let data = 3; const f = (data) => console.log(data); f(2)` and `let data = 3; const f = () => console.log(data); f(2)` – VLAZ May 10 '23 at 06:09

1 Answers1

2

It has to do with closures.

In this example you're passing the value of data to setTimeout at the time of the setTimeout call (2) which will later be passed to the callback, so you get the 1,3,2 output you expect.

(The argument to the callback has the same name but it's an independent variable--it's not the same data as the one declared in the enclosing scope.)

let data = 1;

console.log(data);

data = 2;
setTimeout((data) => {
  console.log(data);
}, 2000,data);

data = 3;

console.log(data);

Just to clarify the distinction between the two data variables here's the same implementation with the argument renamed:

let data = 1;

console.log(data);

data = 2;
setTimeout((banana) => {
  console.log(banana);
}, 2000, data);

data = 3;
console.log(data);

But in this case, where the data argument has been removed from the setTimeout call, your callback is referencing the variable from the outer scope, and by the time the callback runs its value has already been changed to 3. So you get 1,3,3.

let data = 1;
console.log(data);

data = 2;
setTimeout(() => {   // argument removed from callback function
  console.log(data);
}, 2000,data);

data = 3;
console.log(data);
ray
  • 26,557
  • 5
  • 28
  • 27