pMapValues

pMapValues

  • (mapperFn: AsyncMapperFn) => async (collection: Collection) => Collection
  1. Asynchronously map the values of a collection.

    The mapper function is called for all entries at once. See Notes for an example.

    const inc = async n => n + 1
    const incAll = pMapValues(inc)
    
    await incAll([1, 2, 3]) // is [2, 3, 4]
    const inc = async (n: number) => n + 1
    const incAll = pMapValues(inc)
    
    await incAll([1, 2, 3]) // is [2, 3, 4]
    
    const inc = async n => n + 1
    const incAll = pMapValues(inc)
    
    await incAll([1, 2, 3]) // is [2, 3, 4]
    const inc = async (n: number) => n + 1
    const incAll = pMapValues(inc)
    
    await incAll([1, 2, 3]) // is [2, 3, 4]
    
  2. Sometimes we want to asynchronously map the values of a collection. Below, let's call our mock store API to estimate the shipping for each item in our cart.

    const mockShippingEstimates = {
      broom: '2 days',
      mop: '5 days',
      detergent: '1 day',
    }
    
    const mockStoreApi = {
      estimateShipping: async ({ item, destination }) => {
        const shipping = mockShippingEstimates[item]
        return { item, destination, shipping }
      },
    }
    
    const userLocation = 'cleveland'
    const shoppingCart = ['broom', 'mop', 'detergent']
    const estimateShippingPerItem = pMapValues(mockStoreApi.estimateShipping)
    const itemDestinationArgs = shoppingCart.map(item => ({
      item,
      destination: userLocation,
    }))
    const cartWithShipping = await estimateShippingPerItem(itemDestinationArgs)
    console.log(cartWithShipping)
    // prints
    // [
    //   {
    //     item: broom
    //     destination: cleveland
    //     shipping: 2 days
    //   },
    //   {
    //     item: mop
    //     destination: cleveland
    //     shipping: 5 days
    //   },
    //   {
    //     item: detergent
    //     destination: cleveland
    //     shipping: 1 day
    //   },
    // ]
    type ItemDestination = {
      item: string
      destination: string
    }
    
    const mockShippingEstimates: Record<string, string> = {
      broom: '2 days',
      mop: '5 days',
      detergent: '1 day',
    }
    
    const mockStoreApi = {
      estimateShipping: async ({ item, destination }: ItemDestination) => {
        const shipping = mockShippingEstimates[item]
        return { item, destination, shipping }
      },
    }
    
    const userLocation = 'cleveland'
    const shoppingCart = ['broom', 'mop', 'detergent']
    const estimateShippingPerItem = pMapValues(mockStoreApi.estimateShipping)<
      ItemDestination[]
    >
    const itemDestinationArgs = shoppingCart.map(item => ({
      item,
      destination: userLocation,
    }))
    const cartWithShipping = await estimateShippingPerItem(itemDestinationArgs)
    console.log(cartWithShipping)
    // prints
    // [
    //   {
    //     item: broom
    //     destination: cleveland
    //     shipping: 2 days
    //   },
    //   {
    //     item: mop
    //     destination: cleveland
    //     shipping: 5 days
    //   },
    //   {
    //     item: detergent
    //     destination: cleveland
    //     shipping: 1 day
    //   },
    // ]
    
    const mockShippingEstimates = {
      broom: '2 days',
      mop: '5 days',
      detergent: '1 day',
    }
    
    const mockStoreApi = {
      estimateShipping: async ({
        item,
        destination,
      }) => {
        const shipping = mockShippingEstimates[item]
        return { item, destination, shipping }
      },
    }
    
    const userLocation = 'cleveland'
    const shoppingCart = ['broom', 'mop', 'detergent']
    const estimateShippingPerItem = pMapValues(
      mockStoreApi.estimateShipping
    )
    const itemDestinationArgs = shoppingCart.map(
      item => ({
        item,
        destination: userLocation,
      })
    )
    const cartWithShipping =
      await estimateShippingPerItem(
        itemDestinationArgs
      )
    console.log(cartWithShipping)
    // prints
    // [
    //   {
    //     item: broom
    //     destination: cleveland
    //     shipping: 2 days
    //   },
    //   {
    //     item: mop
    //     destination: cleveland
    //     shipping: 5 days
    //   },
    //   {
    //     item: detergent
    //     destination: cleveland
    //     shipping: 1 day
    //   },
    // ]
    type ItemDestination = {
      item: string
      destination: string
    }
    
    const mockShippingEstimates: Record<
      string,
      string
    > = {
      broom: '2 days',
      mop: '5 days',
      detergent: '1 day',
    }
    
    const mockStoreApi = {
      estimateShipping: async ({
        item,
        destination,
      }: ItemDestination) => {
        const shipping = mockShippingEstimates[item]
        return { item, destination, shipping }
      },
    }
    
    const userLocation = 'cleveland'
    const shoppingCart = ['broom', 'mop', 'detergent']
    const estimateShippingPerItem = pMapValues(
      mockStoreApi.estimateShipping
    )<ItemDestination[]>
    const itemDestinationArgs = shoppingCart.map(
      item => ({
        item,
        destination: userLocation,
      })
    )
    const cartWithShipping =
      await estimateShippingPerItem(
        itemDestinationArgs
      )
    console.log(cartWithShipping)
    // prints
    // [
    //   {
    //     item: broom
    //     destination: cleveland
    //     shipping: 2 days
    //   },
    //   {
    //     item: mop
    //     destination: cleveland
    //     shipping: 5 days
    //   },
    //   {
    //     item: detergent
    //     destination: cleveland
    //     shipping: 1 day
    //   },
    // ]
    
  3. pMapValues calls the mapper function for all entries at once. See async.mapLimit if you want to limit the concurrency.

    const start = new Date().getTime()
    
    const inc = async n => {
      const msPassed = Date.now() - start
      console.log(`ms passed: ${msPassed}, for n = ${n}`)
    
      await pWaitMs(20)
      return n + 1
    }
    const incAll = pMapValues(inc)
    
    await incAll([1, 2, 3])
    const totalMsPassed = Date.now() - start
    console.log(`total ms passed: ${totalMsPassed}`)
    const start = new Date().getTime()
    
    const inc = async (n: number) => {
      const msPassed = Date.now() - start
      console.log(`ms passed: ${msPassed}, for n = ${n}`)
    
      await pWaitMs(20)
      return n + 1
    }
    const incAll = pMapValues(inc)<number[]>
    
    await incAll([1, 2, 3])
    const totalMsPassed = Date.now() - start
    console.log(`total ms passed: ${totalMsPassed}`)
    
    const start = new Date().getTime()
    
    const inc = async n => {
      const msPassed = Date.now() - start
      console.log(
        `ms passed: ${msPassed}, for n = ${n}`
      )
    
      await pWaitMs(20)
      return n + 1
    }
    const incAll = pMapValues(inc)
    
    await incAll([1, 2, 3])
    const totalMsPassed = Date.now() - start
    console.log(`total ms passed: ${totalMsPassed}`)
    const start = new Date().getTime()
    
    const inc = async (n: number) => {
      const msPassed = Date.now() - start
      console.log(
        `ms passed: ${msPassed}, for n = ${n}`
      )
    
      await pWaitMs(20)
      return n + 1
    }
    const incAll = pMapValues(inc)<number[]>
    
    await incAll([1, 2, 3])
    const totalMsPassed = Date.now() - start
    console.log(`total ms passed: ${totalMsPassed}`)