javascriptpromise

can not setTimeout with Promise


I was trying to use Promise to test different ways of using Promise then I encountered these problems.

I thought that the result will wait for 3000ms then print hello world 1 and then continuously wait for 2000ms to print hello world 2. However, after printing hello world 1, hello world 2 immediately appears.

Can any experts explain for me why this happened?

const helloWorld = new Promise((resolve, reject) => {
  setTimeout(() => {
    let temp = true;
    if (temp) {
      resolve("hello world 1");
    } else {
      reject("error occured");
    }
  }, 3000)
});

const helloWord2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    let temp = true;
    if (temp) {
      resolve("hello world 2");
    } else {
      reject("error occured");
    }
  }, 2000)
});

helloWorld.then((value) => {
  console.log(value);
  helloWord2.then((value) => {
    console.log(value);
  })
});


Solution

  • The issue is that whatever function you place in you Promise triggers right away, not when it is referenced. A promise object is simply one that either store a result or a a status of 'no value yet', not a lambda that can be triggered on command. If you change your timeout functions to include a console.log, you can see the true runtime of these functions.

    const helloWorld = new Promise((resolve,reject) => {
        setTimeout(() => {
            let temp = true;
            console.log("hello world 1");
            if(temp){
                resolve("hello world 1");
            }else {
                reject("error occured");
            }
        },3000)
    });
    
    const helloWord2 = new Promise((resolve,reject) => {
        setTimeout(() => {
            let temp = true;
            console.log("hello world 2");
            if(temp){
                resolve("hello world 2");
            }else{
                reject("error occured");
            }
        },2000)
    });
    
    helloWorld.then((value) => {
        console.log(value);
        helloWord2.then((value) => {
            console.log(value);
        })
    });

    You will see the second one print out first, as it has a shorter timeout. Then the first one. You will then see your then() block execute. This block will not execute until the first Hello World timeout finishes, which by that time the second Hello World's Promise has already resolved to a value of 'hello world 2', which causes it to print immediately.

    One way to resolve this issue is to store helloWorld2 as a new lambda returning the Promise, rather than as a Promise. This way, the helloWorld2 timeout will not be triggered until helloWorld1 resolves, like such:

    const helloWorld = new Promise((resolve,reject) => {
        setTimeout(() => {
            let temp = true;
            if(temp){
                resolve("hello world 1");
            }else {
                reject("error occured");
            }
        },3000)
    });
    
    const helloWord2Lambda = () => { return new Promise((resolve,reject) => {
        setTimeout(() => {
            let temp = true;
            if(temp){
                resolve("hello world 2");
            }else{
                reject("error occured");
            }
        },2000)
    })};
    
    helloWorld.then((value) => {
        console.log(value);
        helloWord2Lambda().then((value) => {
            console.log(value);
        })
    });