Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

I have no idea why setTimeout wrapping promise not working as i expected

I have this code.

const testArray = [1, 2, 3, 4, 5];

const test = async () => {
    return Promise.resolve().then(() => {
        console.log("Testing console log: ", new Date());
    });
};

const testPromises = testArray.map(async (value) =>
    new Promise((resolve) => setTimeout(resolve, 2000)).then(() => test())
);

const testResult = testPromises.reduce(
    (p, testPromise) => p.then(() => testPromise),
    Promise.resolve()
);

So i expected resolve promises made with testArray map function sequentially with setTimeout worked and log the messsage with 2 seconds interval.

but it is logging at the same time.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I have no idea why this is not working.

>Solution :

The issue is with your testPromises. It creates 5 promises that resolve after 2 seconds simultaneously upon the declaration. When they are declared, the setTimeout countdowns are already ticking.

const testPromises = testArray.map(async (value) =>
    new Promise((resolve) => setTimeout(resolve, 2000)).then(() => test())
);
[Promise, Promise, Promise, Promise, Promise]

What you actually want is to create functions that return a Promise using the map function, so the countdown only ticks when it is called.

const testPromises = testArray.map((value) =>
    () => new Promise((resolve) => setTimeout(resolve, 2000)).then(() => test())
);
[() => Promise, () => Promise, () => Promise, () => Promise, () => Promise]

and then call that function to create the Promise in the reduce sequence:

const testResult = testPromises.reduce(
    (p, testPromise) => p.then(() => testPromise()),
    Promise.resolve()
);

Here’s the full code:

const testArray = [1, 2, 3, 4, 5];

// no need to use async when it returns a Promise explicitly
const test = () => {
  return Promise.resolve().then(() => {
    console.log("Testing console log: ", new Date());
  });
};

// map into a funtion that returns a Promise instead
const testPromises = testArray.map((value) =>
  () => new Promise((resolve) => setTimeout(resolve, 2000)).then(() => test())
);


// when chaining on the Promise using reduce function, call the testPromise() function to create the Promise that resolves after 2 seconds on the fly
const testResult = testPromises.reduce(
  (p, testPromise) => p.then(() => testPromise()),
  Promise.resolve()
);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading