Concurrency model і Цикл Подій

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

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 повертає значення, даний стек очищається.

Купа

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

Черга

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

Цикл подій

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

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

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

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

Кожне повідомлення опрацьовується повністю до початку опрацювання наступного. This offers some nice properties when reasoning about your program, including the fact that whenever a function runs, it cannot be pre-empted and will run entirely before any other code runs (and can modify data the function manipulates). This differs from C, for instance, where if a function runs in a thread, it can be stopped at any point to run some other code in another thread.

A downside of this model is that if a message takes too long to complete, the web application is unable to process user interactions like click or scroll. The browser mitigates this with the "a script is taking too long to run" dialog. A good practice to follow is to make message processing short and if possible cut down one message into several messages.

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

In web browsers, messages are added any time an event occurs and there is an event listener attached to it. If there is no listener, the event is lost. So a click on an element with a click event handler will add a message--likewise with any other event.

Calling setTimeout will add a message to the queue after the time passed as a second argument. If there is no other message in the queue, the message is processed right away; however, if there are messages, the setTimeout message will have to wait for other messages to be processed. For that reason the second argument indicates a minimum time and not a guaranteed time.

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

Zero delay doesn't actually mean the call back will fire-off after zero milliseconds. Calling setTimeout with a delay of 0 (zero) milliseconds doesn't execute the callback function after the given interval. The execution depends on the number of awaiting tasks in the queue. In the example below the message ''this is just a message'' will be written to the console before the message in the callback gets processed, because the delay is the minimum time required for the runtime to process the request, but not a guaranteed time.

(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"

Several runtimes communicating together

A web worker or a cross-origin iframe has its own stack, heap, and message queue. Two distinct runtimes can only communicate through sending messages via the postMessage method. This method adds a message to the other runtime if the latter listens to message events.

Never blocking

A very interesting property of the event loop model is that JavaScript, unlike a lot of other languages, never blocks. Handling I/O is typically performed via events and callbacks, so when the application is waiting for an IndexedDB query to return or an XHR request to return, it can still process other things like user input.

Legacy exceptions exist like alert or synchronous XHR, but it is considered as a good practice to avoid them. Beware, exceptions to the exception do exist (but are usually implementation bugs rather than anything else).

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

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