Skip to content

Example of using p-map to rate limit yourself when making large numbers of concurrent API calls

Notifications You must be signed in to change notification settings

johncmunson/throttling-concurrent-api-calls

Repository files navigation

Sometimes you need to fire off a few dozen concurrent requests to get some data. Great, Promise.all() was made for this.

However, sometimes you might need to fire off a few thousand requests! Now you're at risk of getting blocked or rate-limited by the receiving server, since you're essentially unleashing a DOS attack, intentional or not.

What we need is a way to spread the load we're placing on the external service over a longer period of time... this is called throttling. This is a great use case for p-map by the prolific library author Sindre Sorhus. It's a near drop in replacement for Promise.all(), but allows you to place a limit on the number of concurrent promises that are running at any given time. If you're already using a full-featured Promise library like Bluebird, it might come with a similar method built-in.

Note: Checkout the bluebird branch to see an implementation using Bluebird's map function.

More related packages here.

const pMap = require('p-map')
const Chance = require('chance')

const chance = new Chance()

const userIds = [ 52, 84, 71, 66, 12, 39, 18, 99, 7, 48 ]

// Simulate a network call
const getUser = async (id) => {
  await new Promise(resolve => setTimeout(resolve, 1000))
  return chance.name()
}

const getUsers = async (userIds) => {
  const users = await pMap(userIds, getUser)
  // Using pMap without concurrency is equivalent to...
  // const users = await Promise.all(userIds.map(id => getUser(id)))
  return users
}

const getUsersThrottled = async (userIds) => {
  const users = await pMap(userIds, getUser, { concurrency: 2 })
  return users
}

(async () => {
  console.time('getUsers')
  await getUsers(userIds)
  console.timeEnd('getUsers') // => Roughly 1s

  console.time('getUsersThrottled')
  await getUsersThrottled(userIds)
  console.timeEnd('getUsersThrottled') // Roughly 5s
})()

About

Example of using p-map to rate limit yourself when making large numbers of concurrent API calls

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published