В JS данное поведение реализовано через Event Loop. Это механизм, который позволяет связывать события (истечение таймера, ответ на запрос, явно вызванное событие) и функцию-обработчик, которая вызывается
после того, как это событие наступило. Жирным выделенное означает, что функция вызовется не в сразу же после наступления события, но в произвольный момент времени после. Т.е. она не будет вызвана раньше, чем случится событие, но когда именно она будет вызвана после его наступления – зависит от того, когда Event Loop снова получит управление, т.е. отсутствует понятие прерывания – обработчик не будет вызван, пока выполняется какая-либо другая функция. Соответственно, как только в Event Loop'e больше нет выполняющихся либо ожидающих функций, программа завершается.
setTimeout(function() { console.log('Timeout 1000'); }, 1000 );
setTimeout(function() { console.log('Timeout 2000'); }, 2000);
console.log('Now!');
Выведет
Now!
Timeout 1000
Timeout 2000
И завершится, хотя программа достигла конца после вывода "Now!"