MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/MDN-dev-survey

Переклад не закінчено. Будь ласка, допоможіть перекласти цю статтю з англійської.

JavaScript має concurrency model, яка базується на "циклі подій". Дана модель абсолютно інша від моделей в інших мовах програмування таких, як С або Java.

Поняття часу виконання

Наступні розділи пояснють теоретичну модель. Сучасні середовища виконання JavaScript реалізовують і сильно оптимізовують описану семантику.

Візуальне відображення

Стек, купа, черга

Стек

Функція викликається з стеку фреймів (frames).

function foo(b) {
  var a = 10;
  return a + b + 11;
}

function bar(x) {
  var y = 3;
  return foo(x * y);
}

console.log(bar(7));

Коли викликається bar, першим сторюється фрейм, який містить аргументи функції bar і локальні змінні. Коли bar викликає foo, створюється другий фрейм і кладеться на верх першого, він містить аргументи функції foo і локальні змінні. Коли foo повертає значення, верхній фрейм елемент витягується з даного стеку (залишаючи лише виклик фрейму bar). Коли bar повертає значення, даний стек очищається.

Heap

Об'єкти розподіляються в купу, яка є лише назвою, щоб зазначити велику, здебільшого не структуризовану область пам'яті.

Queue

Час виконання JavaScript містить чергу повідомлень, які є списком повідомлень, які мають бути опрацьовані. З кожним повідомленням асоціюється функція. Коли стек має достатнью ємність, тоді береться одне повідомлення з даної черги і обробляється. Обробка складається з виконання пов'язаної функції (і в свою чергу створення початкового стеку фрейма). Повідомлення, яке обробляється, закінчується тоді, коли даний стек стає знову порожнім.

Event loop

Цикл подій отримав таку назву через те, як це зазвичай реалізується або що це нагадує:

while (queue.waitForMessage()) {
  queue.processNextMessage();
}

queue.waitForMessage чекає синхронно на повідомлення, яке має прийти, якщо його ще немає в даний момент.

"Виконувати до завершення"

Кожне повідомлення обробляється повністю, перш ніж обробляти будь-яке інше повідомлення. Це дає деякі приємні властивості при обґрунтуванні вашої програми, включаючи те, що при роботі функції вона не може бути попередньо запущена і працюватиме цілком, перш ніж буде запущено будь-який інший код (і може змінювати дані, які функціонує). Це відрізняється від C, наприклад, де, якщо функція працює в потоці, в будь-якій точці вона може бути зупинена для запуску деякого іншого коду в іншому потоці.

Недоліком цієї моделі є те, що якщо повідомлення займає надто багато часу для завершення, веб-додаток не може обробити взаємодії користувачів, як-от натискання чи прокручування. Браузер пом'якшує це завдяки діалогу "сценарій, що займає надто багато часу для запуску". Надзвичайна практика полягає в тому, щоб зробити обробку повідомлень коротким і, якщо можливо, виключити одне повідомлення в кілька повідомлень.

Додавання повідомлень

У веб-переглядачах додаються повідомлення щоразу, коли виникає подія, і до нього приєднаний слухач події. Якщо немає слухача, подія втрачається. Таким чином, клік на елементі з обробником подій кліка додасть повідомлення, як і будь-яку іншу подію.

Виклик setTimeout додасть повідомлення до черги після закінчення часу як другий аргумент. Якщо в черзі немає іншого повідомлення, це повідомлення негайно обробляється; Однак, якщо є повідомлення, повідомлення setTimeout доведеться зачекати, поки інші повідомлення будуть оброблені. З цієї причини другий аргумент вказує мінімальний час, а не гарантований час.

Нульові затримки

Нульова затримка насправді не означає, що зворотний виклик буде вимикатись після 0 мілісекунд. Виклик setTimeout з затримкою 0 (нуль) мілісекунд не виконує функцію зворотного виклику після заданого інтервалу. Виконання завдання залежить від кількості очікуваних завдань у черзі. У наведеному нижче прикладі повідомлення "" це лише повідомлення "" буде записано в консоль, перш ніж повідомлення в обробці зворотного вилучення буде оброблено, оскільки затримка - це мінімальний час, необхідний для обробки запиту, але не гарантований Час

(function() {

  console.log('this is the start');

  setTimeout(function cb() {
    console.log('this is a msg from call back');
  });

  console.log('this is just a message');

  setTimeout(function cb1() {
    console.log('this is a msg from call back1');
  }, 0);

  console.log('this is the end');

})();

// "this is the start"
// "this is just a message"
// "this is the end"
// "this is a msg from call back"
// "this is a msg from call back1"

'Несколько взаимодействий, сообщающихся вместе'

Веб-працівник або cross-source iframe має свій стек, купу та чергу повідомлень. Два різних режими роботи можуть спілкуватися лише через надсилання повідомлень через метод postmessage. Цей метод додає повідомлення до іншої середовища виконання, якщо останній прослуховує повідомлення про події.

Never blocking

Дуже цікавою властивістю моделі циклу подій є те, що JavaScript, на відміну від багатьох інших мов, ніколи не блокує. Управління введенням / виводом зазвичай виконується за допомогою подій та зворотних викликів, тому, коли програма чекає повернення запиту IndexedDB або повернення запиту XHR, він все ще може обробляти інші речі, такі як введення користувача.

Спадкові винятки існують як тривожні, або синхронний XHR, але це вважається гарною практикою, щоб уникнути їх. Остерігайтеся, існують виключення з винятком (але зазвичай це помилки, а не щось інше).

Мітки документа й учасники

 Зробили внесок у цю сторінку: YevheniiGurinets, piton13
 Востаннє оновлена: YevheniiGurinets,