node.jsoptional-chaining

how to use optional chaining with map operator?


I have a scenario where I am reading a yaml file and based upon the data, make calls to tag aws resources.

await Promise.all(doc?.SQS.map(async (queue)=>{
  // code to tag 1 queue
}))

Now the yaml file may not have a any sqs, in which case doc?.SQS returns undefined as expected. How can I make the map to not run in this scenario ? I tried below but it didn't work as expected.

await Promise.all(doc?.SQS?.map?.(async (queue)=>{
  // code to tag 1 queue
}))

.

await Promise.all(doc?.SQS && doc?.SQS?.map(async (queue)=>{
  // code to tag 1 queue
}))

Solution

  • doc?.SQS?.map() won't run if either doc or SQS is undefined or null. That's the purpose of conditional chaining.

    The problem is, that Promise.all expects an iterable. But if doc.SQS is not defined doc?.SQS?.map(...) results in undefined, which is not iterable. Thus Promise.all throws an error.

    So you can either check before calling Promise.all

    if (doc?.SQS) {
      await Promise.all(doc.SQS.map(...))
    }
    

    or you can ensure, that Promise.all always receives an iterable -- even if it's just an empty array

    await Promise.all(doc?.SQS?.map(...) || []);
    

    or

    await Promise.all((doc?.SQS? || []).map(...));
    

    I personally would opt for the first way, because it seems much more readable, especially if the callback of map is more than a oneliner ...