Во-первых, имейте в виду 2 момента:
(1) JS — однопоточный язык
(2) Контур событий JS является механизмом выполнения JS. Глубокое понимание исполнения JS эквивалентно глубокому пониманию петли событий в JS
1. Три вопроса души: Почему JS однопоточный, зачем он должен быть асинхронным, как однопоточный достигает асинхронности?
Появление технологии тесно связано со сценариями применения в реальном мире.
Точно так же мы ответим на эти три вопроса в сочетании с реальными сценариями.
(1) Почему JS однопоточный? Первоначально JS был разработан для использования в браузере, поэтому представьте, что JS в браузере был бы многопоточным.
Описание сцены:
Итак, теперь есть 2 процесса, процесс 1 и процесс 2. Поскольку они являются многопроцессорными JS, они работают в одном и том же доме в одно и то же время.
процесс1 удалил дом, а процесс2 отредактировал дом и одновременно выдал две противоречивые команды, как браузер должен это выполнить? Думая таким образом, должно быть легко понять, почему JS разработан как однопоточный.
(2) Почему JS должен быть асинхронным? Описание сцены:
Если в JS нет асинхронности, он может выполняться только сверху вниз, а если время парсинга предыдущей строки очень велико, следующий код будет заблокирован. Для пользователя блокировка означает «зависание», что приводит к ухудшению пользовательского опыта. Итак, в JS есть асинхронное выполнение.
(3) Как один поток JS реализует асинхронность? Поскольку JS является однопоточным и может выполняться только в одном потоке, как он реализуется асинхронно?
Это через цикл событий (event loop).Если вы понимаете механизм цикла событий, вы поймете механизм выполнения JS.
2. цикл событий (1) в JS Пример 1, соблюдайте порядок его выполнения
console.log(1)
setTimeout(function(){
console.log(2)
},0)
console.log(3)
Результат: 1 3 2
То есть функции в setTimeout не выполняются немедленно, а откладываются на определенный период времени и выполняются после выполнения определенных условий.Этот тип кода называется асинхронным кодом.
Поэтому здесь мы впервые знаем метод классификации в JS, который заключается в разделении задач на: синхронные задачи и асинхронные задачи.
Описание изображения
Согласно этой классификации: механизм выполнения JS
Сначала определите, является ли JS синхронным или асинхронным, войдите в основной процесс синхронно и войдите в таблицу событий асинхронно. Асинхронные задачи регистрируют функции в таблице событий, и при выполнении условий срабатывания они помещаются в очередь событий. После того, как синхронная задача войдет в основной поток, она будет выполняться до тех пор, пока основной поток не будет простаивать, и отправится в очередь событий, чтобы проверить, есть ли исполняемая асинхронная задача, и если есть, она будет помещена в основной процесс. Вышеупомянутые три шага выполняются в цикле, который является циклом событий.
Итак, в приведенном выше примере можете ли вы описать порядок, в котором он выполняется?
console.log(1) — это синхронная задача, поместите ее в основной поток setTimeout() — это асинхронная задача, которая помещается в таблицу событий и помещается в очередь событий через 0 секунд. console.log(3 — задача синхронизации, поместите ее в основной поток
Когда на панели управления печатаются 1 и 3, основной поток переходит в очередь событий (очередь событий), чтобы увидеть, есть ли исполняемая функция, и выполняет функцию в setTimeout. 3. цикл событий (2) в JS Итак, приведенный выше цикл событий — это мое понимание механизма выполнения JS, пока я не столкнулся со следующим кодом
Пример 2:
setTimeout (функция () { console.log('Таймер запускается') });
новое обещание (функция (разрешение) { console.log('Выполнить цикл for сейчас'); для (вар я = 0; я
console.log('Конец выполнения кода');
Попробуйте проанализировать в соответствии с механизмом выполнения JS, который мы только что изучили выше.
setTimeout является асинхронной задачей и помещается в таблицу событий.
new Promise — это синхронная задача, которая помещается в основной процесс и напрямую выводит console.log('выполнить цикл for сейчас')
Функции в .then являются асинхронными задачами и помещаются в таблицу событий.
console.log('выполнение кода завершается') — это синхронный код, который помещается в основной процесс и выполняется напрямую
Итак, результат [цикл for выполняется немедленно --- выполнение кода завершается --- запускается таймер --- выполняется функция then]?
После личного выполнения результат не такой, а [выполнить цикл for немедленно --- выполнение кода завершается --- выполнить функцию then --- запускается таймер]
Значит, порядок выполнения асинхронных задач, не порядок до и после, а иное оговаривается?На самом деле по способу деления асинхронных и синхронных он не точен.
Точное деление выглядит следующим образом:
макрозадача (макрозадача): включая общий код скрипта, setTimeout, setInterval микрозадача: Promise, process.nextTick
Согласно этой классификации: механизм выполнения JS
Выполните макрозадачу, и если вы встретите микрозадачу в процессе, поместите ее в [очередь событий] микрозадачи После завершения выполнения текущей макрозадачи будет проверена [Очередь событий] микрозадачи, и все микрозадачи в ней будут выполняться по очереди. Повторение вышеуказанных двух шагов в сочетании с циклом событий (1) и циклом событий (2) является более точным механизмом выполнения JS.
Попробуйте проанализировать пример 2 в соответствии с механизмом выполнения, который вы только что узнали:
Сначала выполните задачу макроса по сценарию, найдите setTimeout, поместите его в [очередь] задачи макроса.
При обнаружении нового промиса выполните его напрямую и напечатайте «немедленно выполнить цикл for».
Когда встречается метод then, это микрозадача, и она помещается в [очередь] микрозадачи.
Печать «Выполнение кода завершилось»
После выполнения этого раунда макрозащится задачи, проверьте микрофонные задачи этого раунда и найдите, что есть функция в том способе, распечатайте «Выполнить, затем функцию»
На этом цикл событий этого раунда завершен.
В следующем раунде цикла сначала выполните задачу макроса, обнаружите, что в setTimeout есть функция в [очереди] задачи макроса, выполните и напечатайте «таймер запущен» Таким образом, окончательный порядок выполнения: [выполнить цикл for немедленно --- выполнение кода заканчивается --- выполнить функцию then --- запускается таймер]
- Разговор о setTimeout Что означает этот код setTimeout?Мы обычно говорим: Через 3 секунды будет выполнена функция в setTimeout
setTimeout (функция () {
console.log('выполнено')
},3000)
Но это не строго, точное объяснение таково: через 3 секунды функция в setTimeout будет помещена в очередь событий, а задачи в очереди событий (event queue) будут выполняться только тогда, когда основной поток простаивает.
Так что только если (1) через 3 секунды (2) основной поток простаивает, и в то же время функция будет выполнена через 3 секунды
Если основной поток выполняет много контента и время выполнения превышает 3 секунды, например 10 секунд, то эта функция может быть выполнена только через 10 секунд.