Глядя на исходный код V8 , мы видим, что при создании Promise , он привязан к текущему контексту выполнения, даже если вы не сохраняете его в переменная.
Node* const native_context = LoadNativeContext(context);
Node* const promise = AllocateAndInitJSPromise(context);
Глядя на , как реализуются обещания , мы видим, что цепочки разрешения Promise реализованы в виде простого связанного списка (выделено мое):
Объекты PromiseReaction
образуют односвязный список [...] . В экземпляре JSPromise
они связаны в обратном порядке и снова отображаются в правильном порядке при планировании их в очереди для микрозадач.
Вкратце, V8 связывает Promises с контекстом выполнения, даже если вы не сохраняете их в переменной, а цепочки Promise реализованы в виде связанных списков, что означает, что легко отследить, как только Promise действительно разрешится.
Для более общего понимания того, как асинхронные операции взаимодействуют друг с другом, посмотрите это видео Джейка Арчибальда в цикле событий Javascript.