Using Promise in a for loop, all the .then came later is always be called untill all the first .then is finished running, why is that?



I am new to JavaScript and with the concept of Promise. And I am doing test.

I created a promise and two for loop that runs Promise for 6 times in total, and I knows when they got executed by console.log()

Here’s my code

console.log("testing promise")

let p = new Promise((resolve, reject)=> { //promise take a function as parameter.

    console.log("defining variable a ")
    let a = 2   
    if(a==2){
        console.log("inthe a ==2 block")
        resolve("success")
    }
    else if (a==3){
        reject("fail")
    }
    else if(a==5){
        reject("fail when a =5")
    }
    

})

console.log("before going into for loop")
for(let i=0; i<3; i++){

    p.then((message)=>{
        console.log("the message is "+message);
        return("second message")
    }).then((ak)=>{
        console.log("the message is "+ak);
        return false
    }).catch((message)=>{
        console.log("the message is "+message)
    })
    .finally(()=>{
        console.log("finially block")
    })
}

for(let i=0; i<3; i++){

    p.then((message)=>{
        console.log("the message is "+message);
        return("second message")
    }).then((ak)=>{
        console.log("the message is "+ak);
        return false
    }).catch((message)=>{
        console.log("the message is "+message)
    })
    .finally(()=>{
        console.log("finially block")
    })
}

and here’s how the console be like:

testing promise
script.js:5 defining variable a 
script.js:8 inthe a ==2 block
script.js:21 before going into for loop
3 script.js:25 the message is success
3 script.js:41 the message is success
3 script.js:28 the message is second message
3 script.js:44 the message is second message
3 script.js:34 finially block
3 script.js:50 finially block

Why is the second .then and all the .finally will wait for every single first .then and then being execute?

I know I probably missing some basic concepts in Javascript in my knowledge database stored inside my brain :), please let me know what concept in JS will be regarding this issue, I would take a look, Thanks!

Answer

If you notice, in your example, you referenced/assigned a promise to a variable (let p = new Promise((resolve, reject)=> {....), and then you used the variable p, which now has the reference of the same instance of promise, in your for loops.

Keep in mind that a reference of a promise, once it’s fulfilled, will always return the same result. For example:

const aPromise = new Promise(resolve => resolve(Math.random());

// loop simulation
for (let x = 0; x < 5; x++) {
    // this will print the same generated random number 5 times.
    aPromise.then(result => console.log(result));
}

That’s probably why you saw what your saw in the console.log(). Basically the two for loops executed the same reference of the promise asynchronously, in which each sequence of handlers (.then and .finally) completes at the same time (or almost).

To properly demonstrate what you want to achieve, you will need to execute a new instance of a Promise on every iteration. Another example:

// use a function here instead to trigger a new instance of a promise.
let aPromise = (loopReference) => new Promise(resolve => {
  // generates a 2 digit random number.
  const randomTimeout = (Math.floor(Math.random() * 90 + 10));
  
  const returnValue = `${loopReference} ${randomTimeout}`;
  console.log(`generated value is: ${returnValue}`);
  
  // simulate a process by using a timeout based on the generated random value.
  setTimeout(() => {
    resolve(returnValue);
  }, randomTimeout);
});


// first loop
for (let x = 0; x < 5; x++) {
  aPromise('first loop').then(val => {
    console.log('first then for: ' + val);
    return val;
  }).then(val => {
    console.log('second then for: ' + val);
    return val;
  });
}

// second loop
for (let x = 0; x < 5; x++) {
  aPromise('second loop').then(val => {
    console.log('first then for: ' + val);
    return val;
  }).then(val => {
    console.log('second then for: ' + val);
    return val;
  });
}

You should then see this log with something like:

generated value is: first loop 46
generated value is: first loop 99
generated value is: first loop 75
generated value is: first loop 56
generated value is: first loop 43
generated value is: second loop 60
generated value is: second loop 50
generated value is: second loop 58
generated value is: second loop 68
generated value is: second loop 35

first then for: second loop 35
second then for: second loop 35
first then for: first loop 43
second then for: first loop 43
first then for: first loop 46
second then for: first loop 46
first then for: second loop 50
second then for: second loop 50
first then for: first loop 56
second then for: first loop 56
first then for: second loop 58
second then for: second loop 58
first then for: second loop 60
second then for: second loop 60
first then for: second loop 68
second then for: second loop 68
first then for: first loop 75
second then for: first loop 75
first then for: first loop 99
second then for: first loop 99

Let me know if this clears things up for you. Good luck!



Source: stackoverflow