--- title: Concurrency Model and Event Loop localeTitle: Модель параллелизма и цикл событий --- ## Модель параллелизма и цикл событий Время выполнения Javascript однопоточное, что означает, что он может выполнять один фрагмент кода за раз. Чтобы понять модель параллелизма и цикл событий в Javascript, мы должны сначала ознакомиться с некоторыми общими терминами, которые связаны с ним. Сначала давайте узнаем, что такое стек вызовов. Стек вызовов представляет собой простую структуру данных, которая записывает, где в коде мы в настоящее время. Поэтому, если мы входим в функцию, которая является вызовом функции, она помещается в стек вызовов, и когда мы возвращаемся из функции, она выплывает из стека. Давайте рассмотрим пример кода, чтобы понять стек вызовов, ```javascript function multiply(x,y) { return x * y; } function squared(n) { return multiply(n,n) } function printSquare(n) { return squared(n) } let numberSquared = printSquare(5); console.log(numberSquared); ``` Во-первых, когда код выполняет runtime, он будет считывать каждое из определений функций, но когда он достигнет строки, в которой вызывается первая функция **printSquare (5),** она будет вызывать эту функцию в стек вызовов. Затем эта функция будет выполнена, и перед возвратом она встретит другую **квадрат** функции **(n),** чтобы приостановить ее текущую операцию и нажать эту функцию поверх существующей функции. Он выполняет функцию в этом случае в квадратной функции и, наконец, встречает другую функцию **multiply (n, n),** поэтому он приостанавливает выполнение своих текущих исполнений и толкает эту функцию в стек вызовов. Функция умножается, и возвращается с умноженным значением. Наконец, функция квадратов возвращается и выталкивается из стека, а затем то же самое происходит с printSquare. Конечное квадратное значение присваивается переменной numberSquared. Мы снова сталкиваемся с вызовом функции, в этом случае это оператор console.log (), поэтому среда выполнения выталкивает это в стек, который выполняет его, тем самым печатая квадрат числа на консоли. Следует отметить, что первая функция, которая попадает в стек до того, как выполняется какой-либо из вышеперечисленных программ, является основной функцией, которая в среде выполнения обозначается как «анонимная функция». Поэтому, чтобы суммировать всякий раз, когда вызывается функция, она помещается в стек вызовов, где она выполняется. Наконец, когда функция выполняется с ее выполнением и возвращается либо неявно, либо явно, она будет удалена из стека. Стек вызовов просто записывает в какой момент времени исполняемый функционал. Он отслеживает, какая функция в данный момент выполняется. Теперь мы знаем, что Javascript может выполнять одну вещь одновременно, но это не так с браузером. У браузера есть собственный набор API, таких как setTimeout, XMLHttpRequests, которые не указаны в среде выполнения Javascript. На самом деле, если вы посмотрите исходный код V8, популярную среду исполнения Javascript, которая поддерживает браузеры, такие как Google Chrome, вы не найдете никаких определений. Это связано с тем, что эти специальные веб-API существуют в среде браузера, а не в среде javascript, и вы можете сказать, что эти apis вводят параллелизм в микс. Давайте посмотрим на диаграмму, чтобы понять всю картину. ![Модель параллелизма и события](https://i.imgur.com/rnQEY7o.png) Введены еще несколько терминов **Куча** - это в основном место, где выделяются объекты. **Callback Queue** - это структура данных, в которой хранятся все обратные вызовы. Так как это очередь, поэтому элементы обрабатываются на основе FIFO, который является первым в First Out. **Event Loop** - это то, где все эти вещи объединяются. То, что цикл событий просто делает, это проверять стеки вызовов, и если он пуст, что означает, что в стеке нет функций, он принимает самый старый обратный вызов из очередь обратного вызова и толкает ее в стек вызовов, который в конечном итоге выполняет обратный вызов. Давайте разобраться с примером кода - ```javascript console.log('hi'); setTimeout(function() { console.log('freecodeCamp') },5000); console.log('JS') ``` Когда выполняется первая строка, это console.log (), который является вызовом функции, что означает, что эта функция помещается в стек вызовов, где она выполняет печать «привет» на консоль и, наконец, возвращается и выталкивается из стека. Затем, когда среда выполнения запускает setTimeout (), она знает, что это веб-API, и, следовательно, он отдает браузеру его выполнение. Браузер запускает таймер, а затем среда выполнения JS выталкивает setTimeout () из стека. Он встречает другой вызов console.log (), и поэтому он толкает его в стек вызовов, сообщение «JS» записывается в консоль, а затем оно наконец возвращается, и поэтому последний console.log () удаляется из стека. Теперь стек вызовов пуст. Между тем, пока все это продолжалось, таймер заканчивается, когда прошло 5 секунд, браузер идет вперед и толкает функцию обратного вызова в очередь обратного вызова. Далее цикл событий проверяет, свободен ли стек вызовов или нет. Поскольку он свободен, он выполняет функцию обратного вызова и снова возвращает его в стек вызовов, который выполняет внутри него код. Снова внутри кода есть вызов console.log (), поэтому эта функция переходит в верхнюю часть стека, которая записывает «freecodecamp» в консоль, и, наконец, возвращает, что означает, что она удаляется из стека, и, наконец, обратный вызов всплывает и мы закончили. Чтобы визуализировать это, лучше попробуйте этот инструмент с помощью Phillip Roberts-Loupe [Event Loop Visualizer](http://latentflip.com/loupe/?code=!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D) #### Дополнительная информация: [Филипп Робертс: Какая черта - цикл событий? | ОАО «Союз 2014»](https://www.youtube.com/watch?v=8aGhZQkoFbQ) [Модель параллелизма и Event Loop MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop)