Search code examples
javascriptnode.jspromisees6-promise

Spawning Multiple Promises


I'm not sure this is possible but this is what I'm trying to do. I have a call to a database that returns a promise. In the then I want to iterate over the results and spawn a new promise for each row to make an HTTP request. It's performing all of the HTTP requests but I am not able to chain a then for each request. Here's what I have tried:

Attempt 1

userDao.getBitbucketInfoForUser(token.id, cohortId)
    // Get Bitbucket information and make clones
    .then((teams) => {
        for(const team of teams) {
            console.log('Clone repo ' + sourceRepo + ' for Team-' + team.teamNumber);
            return makeFork(gitInfo, sourceRepo, team);
        }
    })
    .then((result) => {
        const team = result.team;
        console.log('Wait for Team ' + team + ' repo');
    })
    .catch((error) => {
        console.log(error);
        response.status(error.status).json(error).end()
    });

I realized right away that this was dumb because I was returning and breaking out of my loop. So I went to this:

Attempt 2

userDao.getBitbucketInfoForUser(token.id, cohortId)
    // Get Bitbucket information and make clones
    .then((teams) => {
        for(const team of teams) {
            console.log('Clone repo ' + sourceRepo + ' for Team-' + team.teamNumber);
            makeFork(gitInfo, sourceRepo, team)
                .then((result) => Promise.resolve(result));
        }
    })
    .then((result) => {
        const team = result.team;
        console.log('Wait for Team ' + team + ' repo');
    })
    .catch((error) => {
        console.log(error);
        response.status(error.status).json(error).end()
    });

This time it went through and made all of the calls in makeFork but only ran the then once. Next I tried this:

Attempt 3

userDao.getBitbucketInfoForUser(token.id, cohortId)
    // Get Bitbucket information and make clones
    .then((teams) => {
        for(const team of teams) {
            console.log('Clone repo ' + sourceRepo + ' for Team-' + team.teamNumber);
            new Promise((resolve, reject) => resolve(makeFork(gitInfo, sourceRepo, team)));
        }
    })
    .then((result) => {
        const team = result.team;
        console.log('Wait for Team ' + result + ' repo');
    })
    .catch((error) => {
        console.log(error);
        response.status(error.status).json(error).end()
    });

This resulted in the exact same behavior as Attempt 2. Is there a way to do what I want?


Solution

  • You're close. As noted by other users Promise.all is exactly what you want, even if you need to act on each element individually.

    userDao.getBitbucketInfoForUser(token.id, cohortId)
        // Get Bitbucket information and make clones
        .then((teams) => {
            // Act on each element individually.
            const teamPromises = teams.map((team) => {
                return makeFork(gitInfo, sourceRepo, team).then((result) => {
                    const team = result.team;
                    console.log('Wait for Team ' + team + ' repo');
                });
            });
            // Then resolve everything.
            return Promise.all(teamPromises);
        })
        .catch((error) => {
            console.log(error);
            response.status(error.status).json(error).end()
        });