Home > Net >  How to build an eventual return value though multiple promises
How to build an eventual return value though multiple promises

Time:10-03

How do I chain some promises (NodeJS) together to continually enhance and object with new data and return the final object at the end of the chain. ie:

return getOrder().then((order) => {
    
    return StatusMachine.getStatus(order.orderId);
    
}.then((status) => { 
    
    // get status response
    // how do I access the "Order" in the previous then
    // so I can do something like 
    order.status = status;
    return order;
    
}).then((order) => {

    return Shipping.getTrackingNumber(order.orderId);

}).then((tracking) => {

    order.trackingNumber = tracking;
    return order

});

Goal here is to load an order, then query its status and add it to the order, then query its tracking number and add it to the order. Currently, I'm setting Order as a global variable so that I can access it from every then() function and then in the final then(), I'm simply returning the global Order variable. However, that doesn't feel right.

CodePudding user response:

To get order & status you need to wrap it with async function like this.

getOrder()
  .then(async (order) => { // <--
    const status = await StatusMachine.getStatus(order.orderId)  // <-- await for status
    return { order, status }
  })
  .then(({ status, order }) => {
    order.status = status
    return Promise.resolve(order) // if you are going to chain `.then` again then you have to return promise (converting this to async function will also works) 
  })
//.....

But I high recommend going full async, its much more readable and error handling becomes super easy

const getOrderWithMetadata = async () => {
  const order = await getOrder()
  const status = await StatusMachine.getStatus(order.orderId)
  order.status = status
  const tracking = await Shipping.getTrackingNumber(order.orderId)
  order.trackingNumber = tracking
  return order
}

or with Promise.all


const getOrderWithMetadataBetter = async () => {
  const order = await getOrder()
  const [status, tracking] = await Promsie.all([ // waits for both to complete, throws error if anyone of them fails. 
    StatusMachine.getStatus(order.orderId),
    Shipping.getTrackingNumber(order.orderId),
  ])
  order.status = status
  order.trackingNumber = tracking
  return order
}
  • Related