To make concurrent asynchronous requests in NodeJS (Javascript), we can take advantage of
the setTimeout
function and use it together with async/await
, plus trusty old count
.
What we are aiming for here is that 3 requests get sent asynchronously, but the promise they're contained in only resolves when ALL 3 have returned. If it takes too long, we want to reject the promise, since the data has likely become stale.
Originally I tried using Promise.all()
, but ran into problems with it. The following implementation worked
MUCH better for me.
const makeRequest = () => {
const p = new Promise((resolve, reject) => {
setTimeout(() => resolve('hello'), 1000) // Just use a timer to mock a real HTTP request
})
p.catch(err => console.log(err))
return p
}
const makeConcurrentRequests = endpoints => {
const p = new Promise((resolve, reject) => {
let results = []
let count = 0
setTimeout(async() => {
results[0] = await makeRequest(endpoints[0])
count++
console.log('Result 1:', results[0])
})
setTimeout(async() => {
results[1] = await makeRequest(endpoints[1])
count++
console.log('Result 2:', results[1])
})
setTimeout(async() => {
results[2] = await makeRequest(endpoints[2])
count++
console.log('Result 3:', results[2])
})
console.log('This should execute fist...')
/*
Now we'll use a timer to ensure that all our requests
have returned before a threshold. E.g. in trading, if
it's taken more than x milliseconds for data to return,
the data is considered stale and useless, so we may as
well ignore it and move on.
*/
const intervalCount = 0
const int = setInterval(() => {
if (count === 3) {
console.log(`makeConcurrentRequests finished after ${intervalCount * 100} ms`)
resolve(allDepths)
clearInterval(int)
}
if (intervalCount > 20) {
reject(`getAllDepthsAsync timed out after 2000 ms...`)
clearInterval(int)
}
intervalCount++
}, 100)
})
}