Як JavaScript обробляє відповіді AJAX у фоновому режимі?


139

Оскільки JavaScript запускається в один потік, після запиту AJAX, що насправді відбувається у фоновому режимі? Я хотів би глибше зрозуміти це, чи може хтось пролити трохи світла?



3
Код JavaScript є однопоточним (за винятком веб-працівників), але не браузер, який працює під керуванням JavaScript ...
Хуан Мендес

@JuanMendes Чи працює JavaScript в одному потоці, а черга подій працює в іншій потоці?
Shaun Luttin

1
@ShaunLuttin Ні, черга подій - це те, що стартує JavaScript
Хуан Мендес

Відповіді:


213

Під обкладинками у javascript є черга подій. Кожен раз, коли завершується виконання потоку javascript, він перевіряє, чи є ще одна подія в черзі на обробку. Якщо є, він витягує його з черги і запускає цю подію (наприклад, натискання миші).

Натуральна мережа коду, що лежить під викликом ajax, буде знати, коли буде виконано відповідь ajax, і подія буде додана до черги подій javascript. Від того, наскільки власний код знає, коли виконується виклик ajax, залежить від реалізації. Він може бути реалізований за допомогою потоків, а також може бути сам подій (це насправді не має значення). Сенс реалізації полягає в тому, що коли відповідь на ajax виконана, якийсь нативний код буде знати, що це зроблено, і покладе подію в чергу JS.

Якщо в даний час не працює Javascript, подія буде негайно запущена, що запустить обробник відповіді ajax. Якщо в цей час щось запущено, подія буде оброблена після завершення поточного потоку JavaScript. Двигун javascript не повинен проводити жодного опитування. Коли фрагмент Javascript закінчує виконувати, двигун JS просто перевіряє чергу подій, щоб побачити, чи є ще щось, що потрібно запустити. Якщо це так, він вискакує наступну подію з черги та виконує її (викликає одну або кілька функцій зворотного виклику, які зареєстровані для цієї події). Якщо нічого не стоїть у черзі подій, то інтерпретатор JS має вільний час (збирання сміття або простою), поки якийсь зовнішній агент не поставить щось інше у чергу подій та знову його прокине.

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

Ось кілька статей про деталі:


Дякую за це. Я підозрював, що це було так, але добре це точно знати. У мене є цикл for, в якому я надсилаю безліч запитів "ajax". У своєму обробнику (для кожного запиту - повертається у довільному порядку) я запускаю деякий код, який може зайняти деякий час. Добре знати, що це обов'язково спрацює.
iPadDeveloper2011

4
@telandor - події запускаються у порядку FIFO (можливо, є деякі винятки з крайнього випадку, але намір є FIFO). Деякі події трактуються дещо інакше. Наприклад, події, що рухаються мишею, не збираються в черзі (можливо, тому що вони можуть легко переповнити чергу). Коли миша рухається і подія переміщення миші вже стоїть у черзі, а інших нових подій у черзі немає, вона оновлюється останньою позицією, а не додається нова подія. Я б здогадався, що події таймеру інтервалу, ймовірно, також трактуються спеціально, щоб уникнути їх накопичення у черзі.
jfriend00

2
@telandor - що вам потрібно пояснити далі? Це FIFO. До своєї відповіді я додав ще кілька довідкових статей. Єдині виключення з FIFO, про які я знаю, - це негайно викликані події. Ви закликаєте .focus()елемент, і це викликає пару інших подій, таких як подія "розмиття" на об'єкті з фокусом. Ця подія розмивання відбувається синхронно і не проходить через чергу подій, тому це станеться безпосередньо перед іншими речами, які можуть бути у черзі подій. На практиці я ніколи не вважав, що це викликає практичне занепокоєння.
jfriend00

2
@telandor - на документ браузера не існує декількох черг. Є одна черга, і все відбувається послідовно FIFO вхід / вихід. Таким чином, очікування та відповіді Ajax, події миші та події клавіатури проходять в одній черзі. Хто б не ставив у чергу, першим запускається.
jfriend00

1
@CleanCrispCode - Thx. Я додав це як корисне посилання на свою відповідь.
jfriend00

16

Ви можете знайти тут дуже повну документацію про події обробки в JavaScript.
Він написаний хлопцем, який працює над реалізацією javascript у браузері Opera.

Точніше, подивіться на заголовки: "Потік подій", "Черга подій" та "Події, що не користувачі": ви дізнаєтесь, що:

  1. Javascript працює в один потік для кожної вкладки чи вікна браузера.
  2. Події встановлюються в черзі та виконуються послідовно.
  3. XMLHttpRequest запускається реалізацією, а зворотні виклики запускаються за допомогою черги подій.

Примітка. Оригінальним посиланням було: посилання , але воно тепер мертве.


1

Хочу трохи детальніше розповісти про реалізацію ajax, згадану у відповідях.

Хоча (звичайний) виконання Javascript є НЕ багато-- як зазначено також в наведених вище відповідей - тим НЕ менш , реальне поводження з AJAX responses(а також обробки запитів) є НЕ Javascript, і це - як правило , - це багато-. (див. реалізацію джерела хромування XMLHttpRequest, про який ми поговоримо вище)

і я поясню, візьмемо наступний код:

var xhr = new XMLHttpRequest();

var t = Date.now;
xhr.open( "GET", "https://swx.cdn.skype.com/shared/v/1.2.15/SkypeBootstrap.min.js?v="+t(), true );

xhr.onload = function( e ) {
		console.log(t() + ': step 3');
    
    alert(this.response.substr(0,20));
};
console.log(t() + ': step 1');
xhr.send();
console.log(t() + ': step 2');

after an AJAX request is made(- після кроку 1), тоді, поки ваш js-код триває виконання (крок 2 і після), браузер починає справжню роботу: 1. форматування запиту tcp 2. відкриття сокета 3. надсилання заголовків 4. рукостискання 5. надсилання тіло 6. відповідь очікування 7. заголовки читання 8. тіло зчитування тощо. вся ця реалізація зазвичай виконується в іншому потоці паралельно виконанню коду js. Наприклад, згадана реалізація хрому використовує Threadable Loader, що переходить до 😉, (також можна скласти враження, переглянувши вкладку мережі завантаження сторінки, ви побачите кілька одночасних запитів).

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.