Асинхронный - Awaaaaaaaaaat?

Устали задавать одни и те же вопросы Event Loop и this в ваших интервью по JavaScript? Хотя основы очень важны, с тех пор JavaScript пошел дальше. МНОГО.
В этой серии я предлагаю несколько примеров вопросов для собеседования по современному JavaScript, которые раскрывают понимание кандидатом состояния языка в его нынешнем виде.

Итак, вы говорите, что понимаете Обещания. Вы даже знаете Promises 2.0, async - await? А Генераторы даже (3.0)?

Что ж, в таком случае давайте посмотрим на async-await.

Что, по вашему мнению, будет выводить этот образец кода на консоль? Что еще более важно, почему?

function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}


async function add1(x) {
  const a = await resolveAfter2Seconds(20);
  const b = await resolveAfter2Seconds(30);
  return x + a + b;
}
add1(10).then(v => {
  console.log(v);
});


async function add2(x) {
  const p_a = resolveAfter2Seconds(20);
  const p_b = resolveAfter2Seconds(30);
  return x + await p_a + await p_b;
}

add2(10).then(v => {
  console.log(v);
});

Ответ: 60 через 2 секунды и 60 через еще 2 секунды

В add1 выполнение приостанавливается на 2 секунды для первого await, а затем еще на 2 секунды для второго await. Второй таймер не создается, пока первый не сработает. В add2 создаются оба таймера, а затем оба await заблокированы. Это приводит к разрешению через 2, а не за 4 секунды, потому что таймеры работают одновременно. Но оба вызова await по-прежнему выполняются последовательно, а не параллельно.

Мысль: это действительно показывает понимание кандидатом цикла событий, обещаний, а также асинхронного ожидания за один раз. Попробуйте и прокомментируйте!

Код, бессовестно позаимствованный у MDN