pCompose

pCompose

  • (fnArray: async function[]) => async (...args: any[]) => Result
  1. Compose an async function which passes the arguments through an array of async functions

    Each function takes the result of the prior function as its parameter.

    const increment = async n => n + 1
    const double = async n => n * 2
    const toAnswer = async n => 'answer: ' + n
    
    const calculate = pCompose([increment, double, toAnswer])
    await calculate(1) // is 'answer: 4'
    
    const returnFirstArg = pCompose([])
    await returnFirstArg('a', 'b') // is 'a'
    const increment = async (n: number) => n + 1
    const double = async (n: number) => n * 2
    const toAnswer = async (n: number) => 'answer: ' + n
    
    const calculate = pCompose([increment, double, toAnswer])
    await calculate(1) // is 'answer: 4'
    
    const returnFirstArg = pCompose([])
    await returnFirstArg('a', 'b') // is 'a'
    
    const increment = async n => n + 1
    const double = async n => n * 2
    const toAnswer = async n => 'answer: ' + n
    
    const calculate = pCompose([
      increment,
      double,
      toAnswer,
    ])
    await calculate(1) // is 'answer: 4'
    
    const returnFirstArg = pCompose([])
    await returnFirstArg('a', 'b') // is 'a'
    const increment = async (n: number) => n + 1
    const double = async (n: number) => n * 2
    const toAnswer = async (n: number) =>
      'answer: ' + n
    
    const calculate = pCompose([
      increment,
      double,
      toAnswer,
    ])
    await calculate(1) // is 'answer: 4'
    
    const returnFirstArg = pCompose([])
    await returnFirstArg('a', 'b') // is 'a'
    
  2. Sometimes we want to name a set of async functions. Below, we're coding the checkout stage to our online shop. To prep our order, we need to call an API to assign our shipping amount and then make another call to finalize the total. Let's compose a function that does this and call it 'prepForCheckout.'

    const mockSalesTax = 0.08
    const mockShipping = 10
    
    const mockStoreApi = {
      assignShipping: async order => ({
        ...order,
        shipping: mockShipping,
      }),
      finalizeTotal: async order => ({
        ...order,
        salesTax: mockSalesTax,
        total: order.subtotal * (1 + mockSalesTax) + order.shipping,
      }),
    }
    
    const userLocation = 'cleveland'
    const shoppingCart = ['broom', 'mop', 'detergent']
    const order = {
      cart: shoppingCart,
      destination: userLocation,
      subtotal: 26,
    }
    const prepForCheckout = pCompose([
      mockStoreApi.assignShipping,
      mockStoreApi.finalizeTotal,
    ])
    const updatedOrder = await prepForCheckout(order)
    
    console.log(updatedOrder)
    // prints
    // {
    //   cart: [broom, mop, detergent]
    //   destination: cleveland
    //   subtotal: 26
    //   shipping: 10
    //   salesTax: 0.08
    //   total: 38.08
    // }
    type Order = {
      cart: string[]
      destination: string
      salesTax: number
      shipping: number
      subtotal: number
      total: number
    }
    
    const mockSalesTax = 0.08
    const mockShipping = 10
    
    const mockStoreApi = {
      assignShipping: async (order: Order): Promise<Order> => ({
        ...order,
        shipping: mockShipping,
      }),
      finalizeTotal: async (order: Order): Promise<Order> => ({
        ...order,
        salesTax: mockSalesTax,
        total: order.subtotal * (1 + mockSalesTax) + order.shipping,
      }),
    }
    
    const userLocation = 'cleveland'
    const shoppingCart = ['broom', 'mop', 'detergent']
    const order = {
      cart: shoppingCart,
      destination: userLocation,
      subtotal: 26,
    } as Order
    const prepForCheckout = pCompose([
      mockStoreApi.assignShipping,
      mockStoreApi.finalizeTotal,
    ])
    const updatedOrder = await prepForCheckout(order)
    
    console.log(updatedOrder)
    // prints
    // {
    //   cart: [broom, mop, detergent]
    //   destination: cleveland
    //   subtotal: 26
    //   shipping: 10
    //   salesTax: 0.08
    //   total: 38.08
    // }
    
    const mockSalesTax = 0.08
    const mockShipping = 10
    
    const mockStoreApi = {
      assignShipping: async order => ({
        ...order,
        shipping: mockShipping,
      }),
      finalizeTotal: async order => ({
        ...order,
        salesTax: mockSalesTax,
        total:
          order.subtotal * (1 + mockSalesTax) +
          order.shipping,
      }),
    }
    
    const userLocation = 'cleveland'
    const shoppingCart = ['broom', 'mop', 'detergent']
    const order = {
      cart: shoppingCart,
      destination: userLocation,
      subtotal: 26,
    }
    const prepForCheckout = pCompose([
      mockStoreApi.assignShipping,
      mockStoreApi.finalizeTotal,
    ])
    const updatedOrder = await prepForCheckout(order)
    
    console.log(updatedOrder)
    // prints
    // {
    //   cart: [broom, mop, detergent]
    //   destination: cleveland
    //   subtotal: 26
    //   shipping: 10
    //   salesTax: 0.08
    //   total: 38.08
    // }
    type Order = {
      cart: string[]
      destination: string
      salesTax: number
      shipping: number
      subtotal: number
      total: number
    }
    
    const mockSalesTax = 0.08
    const mockShipping = 10
    
    const mockStoreApi = {
      assignShipping: async (
        order: Order
      ): Promise<Order> => ({
        ...order,
        shipping: mockShipping,
      }),
      finalizeTotal: async (
        order: Order
      ): Promise<Order> => ({
        ...order,
        salesTax: mockSalesTax,
        total:
          order.subtotal * (1 + mockSalesTax) +
          order.shipping,
      }),
    }
    
    const userLocation = 'cleveland'
    const shoppingCart = ['broom', 'mop', 'detergent']
    const order = {
      cart: shoppingCart,
      destination: userLocation,
      subtotal: 26,
    } as Order
    const prepForCheckout = pCompose([
      mockStoreApi.assignShipping,
      mockStoreApi.finalizeTotal,
    ])
    const updatedOrder = await prepForCheckout(order)
    
    console.log(updatedOrder)
    // prints
    // {
    //   cart: [broom, mop, detergent]
    //   destination: cleveland
    //   subtotal: 26
    //   shipping: 10
    //   salesTax: 0.08
    //   total: 38.08
    // }
    
  3. When to use pPassThrough vs. pCompose?

    They can often be used interchangeably. Compose allows you to name a group of functions, which can sometimes be helpful. Other times a name is unnecessary, and you just want to pass data through.