Синхронные исключения идут вверх по call stack, пока их не поймает catch.
Отвергнутые Promise идут по цепочке, пока нет rejection handler.
try/catch вокруг кода, который лишь планирует таймер/колбэк, не поймает throw, случившийся позже на другом стеке. Асинхронный API должен сообщать сбой через Promise, error-first callback или своё error-событие.