Search code examples
javascriptasynchronousasync-awaitsettimeoutes6-promise

how to run a Promise in async function more than once?


I'm learning promise and async await, here I want to call addPost function and push an object twice and then I want to loop on that array of objects to see the results, but in this code the result is not as expected. In this when the line hit showDetails() function it's showing only 3 objects but there should be four objects, what am I missing here?

const posts = [{ title: 'Post 1' }, { title: 'Post 2' }];
var count = 3;

const diffFunction = async () => {
    const addPost = new Promise((resolve, reject) => {
        setTimeout(() => {
            posts.push({ title: `Post ${count}` });
            count++;
            resolve(count);
        }, 1000)
    })
    const deletePost = new Promise((res, rej) => {
        setTimeout(() => {
            const deltedPost = posts.pop();
            res(deltedPost);
        }, 2000)
    })

    const showDetails = () => {
        posts.forEach(element => {
            console.log(element.title);
        });
    }
    await addPost;
    await addPost;
    showDetails();
}
diffFunction();


Solution

  • When you create a promise with new Promise(), it starts running immediately. You can test this by running something like new Promise(() => { console.log("hello") }) in your console - you should see an immediate log.

    You can achieve the behaviour you want by defining a function returning a new Promise. That way your promise will only run when you call that function, and each function call will return a different Promise.

    const posts = [{ title: 'Post 1' }, { title: 'Post 2' }];
    var count = 3;
    
    const addPost = () => new Promise((resolve, reject) => {
        setTimeout(() => {
            posts.push({ title: `Post ${count}` });
            count++;
            resolve(count);
        }, 1000)
    })
    
    const deletePost = () => new Promise((res, rej) => {
        setTimeout(() => {
            const deltedPost = posts.pop();
            res(deltedPost);
        }, 2000)
    })
    
    const showDetails = () => {
        posts.forEach(element => {
            console.log(element.title);
        });
    }
    
    const diffFunction = async () => {
        await addPost();
        await addPost();
        showDetails();
    }
    
    diffFunction();

    You can see there I've changed addPost and deletePost to be functions rather than promises.