Почему асинхронный JavaScript показывает другой порядок вывода при медленном выполнении в Chrome DevTools?Javascript

Форум по Javascript
Ответить
Anonymous
 Почему асинхронный JavaScript показывает другой порядок вывода при медленном выполнении в Chrome DevTools?

Сообщение Anonymous »

Я отлаживаю программу JavaScript в Chrome DevTools → вкладка «Источники» и заметил, что порядок выполнения асинхронных задач меняется в зависимости от того, как я использую «Шаг с обходом (F10)».
Вот мой код:

Код: Выделить всё

console.log("Start");

setTimeout(() => {
console.log("Async task1");
}, 2000);

setTimeout(() => {
console.log("Async task2");
}, 1000);

fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => console.log("Fetched data:", json));

console.log("End");
Что я пробовал
Добавил точки останова в каждой строке и использовал переход с обходом (F10).
Наблюдал результат с быстрым и медленным шагом.
Протестировал тот же код в браузерах других разработчиков.
Ожидаемый результат

Код: Выделить всё

Start
End
Fetched data: { ... }
Async task2
Async task1
Начало и завершение должны выполняться первыми (синхронно).
Обещание выборки выполняется следующим (микрозадача).
Обратные вызовы setTimeout выполняются последними (макрозадачи, в порядке таймера).
Что на самом деле происходит
При шаге быстро, порядок вывода соответствует ожидаемому.
При медленном шаге (пауза в несколько секунд между шагами) порядок вывода меняется.
Иногда Async Task1 появляется перед Async Task2 или выборка выполняется в другом порядке.
Другие разработчики не видят этой проблемы.
Порядок вывода меняется в зависимости от того, как долго я делаю паузу перед нажатием «Перешагнуть».
Иногда печатает:

Код: Выделить всё

Start
End
Async task1
Async task2
Fetched data: { ... }
Мое понимание
Приостановка работы отладчика останавливает только основной поток JS.
Таймеры (setTimeout) и обещания (fetch) продолжают работать в фоновом режиме.
К моменту возобновления работы асинхронные задачи могут уже истекнуть, поэтому цикл событий выполняет их немедленно — это меняет порядок вывода.
Микрозадачи (промисы) всегда выполняются раньше макрозадач (таймеров), что влияет на порядок.
Вопросы
Почему приостановка работы отладчика меняет порядок выполнения асинхронных задач?
Как я могу отлаживать асинхронные задачи? код последовательно, чтобы обратные вызовы setTimeout и fetch выполнялись каждый раз в одном и том же порядке?
Существуют ли настройки или методы DevTools, позволяющие сделать отладку предсказуемой для асинхронного JavaScript?
Среда
Браузер: Google Chrome (последняя версия)
Инструменты разработчика: вкладка «Источники»
ОС: Windows 10
Язык: Vanilla JavaScript
Что вы пробовали?
Я добавил точки останова в каждую строку в Chrome DevTools и использовал кнопку «Шаг вперед (F10)» для построчной отладки. Я также протестировал тот же код в браузерах других разработчиков. Я делал паузы между шагами на разную продолжительность, чтобы наблюдать за результатом.
Чего вы ожидали?
Я ожидал, что сначала появятся синхронные журналы («Начало» и «Конец»), затем результат обещания выборки и, наконец, обратные вызовы setTimeout в порядке их таймеров. Ожидаемый результат:

Код: Выделить всё

Start
End
Fetched data: { ... }
Async task2
Async task1
Что на самом деле произошло?
Когда я медленно вошел в отладчик, порядок изменился. Иногда «Асинхронная задача 1» появлялась перед «Асинхронной задачей 2» или даже до результата выборки. Порядок вывода зависел от того, как долго я делал паузу между шагами. Другие разработчики не заметили этой проблемы.

Подробнее здесь: https://stackoverflow.com/questions/797 ... owly-in-ch
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»