In the following, code unhandledRejection doesn't get fired for p2, even though it also gets rejected, albeit later than p1:
process.on('unhandledRejection', (reason, promise) => 
  console.log(`unhandledRejection: ${reason}`));
async function delay(ms) {
  await new Promise(r => setTimeout(r, ms));
}
const p1 = async function f1(){
  await delay(100);
  throw new Error("f1");
}();
const p2 = async function f2(){
  await delay(200);
  throw new Error("f2");
}();
try {
  await Promise.race([p1, p2]);
  //await Promise.race([p1]);
}
catch (e) {
  console.error(e.message);
}
If I change the commented line like this:
  //await Promise.race([p1, p2]);
  await Promise.race([p1]);
... then unhandledRejection does get fired for p2, as expected. The same behavior is observed for Promise.all().
Thus, Promise.race and Promise.all effectively prevent the unhandledRejection event for promises which don't win the race but still get rejected. Is it a documented behavior? I can't seem to find any mentions of that in the specs.