forJ
forJ

Reputation: 4617

how to allow delay in looped http request but also use Promise.all to detect when requests are done

Hi I am trying to allow 50ms before next http request is made to the server but also would like to implement some function when all the request have been made.

I made an example to illustrate what I would like to do.

So below is my example express api

app.get('/morans/test', (req, res) => {
    console.log(`start test request`);
    let targetUrl = `http://-domain-/solr/genea_expression/smplGeoclust?q=text:"GO:0003674"&stats.facet=geohash_3&rows=10320`;
    let i = 0;
    let promises = [];

    console.log(`making request ${i}`);


    for (let i = 0; i < 200; i++) {
        setTimeout(
            () => {
                let testReq = new Promise((resolve, reject) => {
                    http.get(targetUrl, (result) => {
                        result.on('data', (chunk) => {
                            console.log(`working ${i}`);
                        }).on('end', () => {
                            console.log(`ending ${i}`);
                        }).on('error', (err) => {
                            console.log(`this is error message ${err}`);
                        })
                    })
                });

                promises.push(testReq);
            }, 50 * i
        )
    }
    Promise.all(promises).then(() => {
        console.log(`done`);
    });
});

The delay works fine; however, Promise.all(promises)... is getting a premature trigger (console.log('done') triggers as soon as first request is made). It works fine when there is no timeout so I am thinking that the setTimeout is not allowing enough time for promise to be pushed to promises array. How can I write a code so that http request is made in every 50ms but also know when all the requests are successfully returned?

Upvotes: 0

Views: 39

Answers (1)

trincot
trincot

Reputation: 350345

You are calling Promise.all at a time your promises array is empty, since none of the time outs has expired yet.

You could move that Promise.all call inside your timeout callback, right after the push, and check the length of that array:

for (let i = 0; i < 200; i++) {
    setTimeout(
        () => {
            // ...etc ... etc
            promises.push(testReq);
            if (promises.length == 200) { // <---- add this block
                Promise.all(promises).then(() => {
                    console.log(`done`);
                });
            } 
        }, 50 * i
    )
}

Also make sure you call resolve() within your new Promise callback, otherwise your promises will stay pending:

                    .on('end', () => {
                        console.log(`ending ${i}`);
                        resolve();
                    })

See the documentation on http.get to see how to actually get the response data... It would make sense to call resolve with that data as argument.

Upvotes: 2

Related Questions