Будет ли это вызывать переполнение стека?
Нет, не будет.Согласно спецификации обещания, .then()
ожидает полного разворачивания стека и затем вызывается после очистки стека (по существу, на следующем такте цикла обработки событий).Таким образом, .then()
уже вызывается асинхронно после того, как обработано текущее событие и стек размотан.Вам не нужно использовать setTimeout()
, чтобы избежать наращивания стека.
Ваш первый пример кода не будет иметь никакого наращивания стека или переполнения стека, независимо от того, сколько раз вы его повторяете.
В спецификации Promises / A + , раздел 2.2.4, говорится следующее:
2.2.4 onFulfilled или onRejected не должны вызываться, пока стек контекста выполнения не содержит только платформукод.[3.1].
И, «код платформы» определен здесь в 3.1:
«код платформы» означает код реализации, среду и код реализации обещания.На практике это требование гарантирует, что onFulfilled и onRejected выполняются асинхронно после поворота цикла событий, в котором затем вызывается, и со свежим стеком.Это может быть реализовано с помощью механизма «макро-задачи», такого как setTimeout или setImmediate, или с помощью механизма «микро-задачи», такого как MutationObserver или process.nextTick.Поскольку реализация обещания считается кодом платформы, она сама может содержать очередь планирования задач или «батут», в котором вызываются обработчики.
В спецификации обещания ES6 используются разные слова, ногенерирует тот же эффект.В ES6 обещание .then()
выполняется путем инициализации задания и последующего разрешения обработки этого задания, а задание обрабатывается только тогда, когда другой код не запущен и стек пуст.
Это способ выполнения, такой какзадание описано в спецификации ES6 :
Задание - это абстрактная операция, которая инициирует вычисление ECMAScript, когда в данный момент не выполняется никакого другого вычисления ECMAScript.Абстрактная операция Job может быть определена для принятия произвольного набора параметров работы.
Выполнение Job может быть инициировано, только если нет запущенного контекста выполнения, а стек контекста выполнения пуст ,PendingJob - это запрос на будущее выполнение задания.PendingJob - это внутренняя запись, поля которой указаны в таблице 25. После запуска задания задание всегда выполняется до завершения.Никакое другое задание не может быть инициировано до тех пор, пока текущее задание не будет завершено.Однако текущее запущенное задание или внешние события могут привести к постановке в очередь дополнительных PendingJobs, которые могут быть инициированы через некоторое время после завершения текущего запущенного задания.