user1169587
user1169587

Reputation: 1340

why the following javascript promise chaining not in sequence

<script>
async function myDisplay() {
  let myPromise = new Promise(function(myResolve, myReject) {
    setTimeout(function() { alert(1) }, 10000);
  }).then(setTimeout(function() { alert(2) }, 5000))
  .then(setTimeout(function() { alert(3) }, 2000));
  
}

myDisplay();
</script>

I see promise chaining can make multiple asynchronous tasks to execute in sequence, so I expect the output sequence is alert(1), alert(2), alert(3), but the actual output is alert(3), alert(2), alert(1), why?

Upvotes: 0

Views: 98

Answers (4)

Shruthi Reddy
Shruthi Reddy

Reputation: 1

well, I'm not sure how you were able to write settimeout directly instead of a callback function, what I noticed is the promise is fulfilled immediately, so based on the timer inside the setTimeout, the order of alerts is executed.

check this article: https://www.geeksforgeeks.org/how-to-wrap-settimeout-method-in-a-promise/#:~:text=We%20can%20wrap%20setTimeout%20in,This%20function%20returns%20a%20promise.

someone please clarify why settimeout is returning a promise or behaving as a promise

Upvotes: 0

Rob Monhemius
Rob Monhemius

Reputation: 5144

If you want to do promise chaining you need to return a new promise from the previous one. Like this:

async function myDisplay() {
    new Promise( (resolve, reject) => {
      setTimeout(function() { resolve(1) }, 10000);
    })
    .then( result => { 
      console.log(result); 
      return new Promise( (resolve, reject) => {
        setTimeout(function() { resolve(2) }, 5000);
      }) 
    })
    .then(result => {
      console.log(result); 
      return new Promise( (resolve, reject) => {
        setTimeout(function() { resolve(3) }, 2000);
      }) 
    })
    .then(result => { console.log(result); } )
}

myDisplay();

setTimeout just starts a timer that counts down from the moment it is created. So actually creating the promises beforehand causes them to trigger instantly if the timeout has already expired.

const prom_1 = new Promise( (resolve, reject) => {
  setTimeout(function() { resolve(1) }, 10000);
});

const prom_2 = new Promise( (resolve, reject) => {
  setTimeout(function() { resolve(2) }, 5000);
});

const prom_3 = new Promise( (resolve, reject) => {
  setTimeout(function() { resolve(3) }, 2000);
});

prom_1
.then( result => { 
  console.log(result); 
  return prom_2;
})
.then(result => {
  console.log(result); 
  return prom_3;
})
.then(result => { console.log(result); } )

Upvotes: 2

timotgl
timotgl

Reputation: 2925

What you expected to happen would work this way, nesting instead of chaining:

setTimeout(
  () => {
    alert(1);
    setTimeout(
      () => {
        alert(2);
        setTimeout(
          () => {
            alert(3);
          },
          2000
        );
      },
      5000
    );
  },
  10000
);

Upvotes: -1

Da Mahdi03
Da Mahdi03

Reputation: 1608

What your code does is it sets your first timeout, then when that first timeout is set, it returns the promise and then proceeds to set the next timeout, which has a shorter length, and so forth. Because the JavaScript engine is working fast, you're going to have a 10 second timeout, then a 5 second timeout, then a 2 second timeout. If you wanted the promise to wait those 10 seconds BEFORE setting the next 5 second timeout, you would need to add some code that would resolve your promise after 10 seconds, allowing it to move on to the next chained function.

Upvotes: 1

Related Questions