2

I am fairly new to Node.JS, and I really hate the syntax of Promise.all returning an array.

eg.

const requiredData = await Promise.all([
        getFirst(city),
        getSecond(hubIds),
        getThird(city, customerCategoryKey),
        getFourth(request)
    ])

const firstData = requiredData[0];
const secondData = requiredData[1];
const thirdData = requiredData[2];
const fourthData = requiredData[3];

I need to individually fetch them in separate lines of code. Isn't there a way like

const {
firstData,
secondData,
thirdData,
fourthData
} = await Promise.all([
        getFirst(city),
        getSecond(hubIds),
        getThird(city, customerCategoryKey),
        getFourth(request)
    ])

Basically, I'd really like if there is a cleaner way than the first code snippet.

TIA!

  • 6
    You could just use [array destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) to turn the array into separate values – Reyno May 16 '20 at 16:55
  • 3
    OP basically already had it. Just had to replace the brackets in `const { ... } = await` with `const [ ... ] = await` using array destructuring instead of object destructuring – user120242 May 16 '20 at 17:40

2 Answers2

6

As mentioned in the comments you can use Array destructor instead of using Object destructor:

(async () => {
  const promise1 = Promise.resolve(3);
  const promise2 = 42;
  const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, "foo");
  });

  // get all elements as variables
  const [p1, p2, p3] = await Promise.all([promise1, promise2, promise3]);

  console.log(p1, p2, p3);
})();
ROOT
  • 11,363
  • 5
  • 30
  • 45
  • This solution works! Btw any way I can directly assign these variables to an object, all happening in one line? – Gitesh Khanna May 17 '20 at 09:23
  • not sure If got your question right, destructing works only for the same type, i.e Array destruct to Array, Object destruct to Object, so I think you have to do this manually if your want it to be in an Object. but check this [answer](https://stackoverflow.com/questions/38242744/destructure-array-to-object-property-keys/38244614#38244614) – ROOT May 17 '20 at 09:46
-3

In case it's not obvious, if you're okay running the promises in serial order, you can await them inline -

const main = async () =>
{ const a = await mock("one")
  const b = await mock("two")
  const c = await mock("three")
  const d = await mock("four")

  console.log(a, b, c, d)
}

// test funcs
const rand = n =>
  Math.floor(Math.random() * n)

const mock = (x) =>
  new Promise(r => setTimeout(r, rand(1000), x))

// run
console.log("loading...")
main().catch(console.error)

// loading...
// one two three four

If you want to run the promises in parallel but retrieve assign the values by name, we could fromDescriptor which does the wiring for us -

const fromDescriptor = (desc = {}) =>
  Promise.all( 
    Object
      .entries(desc)
      .map(([ k, px ]) => px.then(x => [ k, x ]))
  )
  .then(Object.fromEntries)

const main = async () =>
{ const init =            
    { a: mock("one")
    , b: mock("two")
    , c: mock("three")
    , d: mock("four")
    }
  
  const { a, b, c, d } =
    await fromDescriptor(init)

  console.log(a, b, c, d)
}

// test funcs
const rand = n =>
  Math.floor(Math.random() * n)

const mock = (x) =>
  new Promise(r => setTimeout(r, rand(1000), x))

// run
console.log("loading...")
main().catch(console.error)

// loading...
// one two three four
Mulan
  • 129,518
  • 31
  • 228
  • 259
  • Your comment on "You could destructure the value using .then" suggests that you can only destructure values using `.then`. I think it's misleading to only show your example with `.then` , in particular, when the author is using `async/await`. – Dan Starns May 16 '20 at 18:26