Рубріки: Back-end

«Це величезна прогалина у більшості розробників»: 6 головних питань на співбесіді з Node.js

Владислав Хирса

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

1Що таке Event Loop в Node.js

Event Loop — це цикл, за допомогою якого Node.js має змогу виконувати неблокуючі операції I/O — input/output.

І ще є дуже важливим, що Event Loop — це тільки «серце» великого механізму відомої бібліотеки libuv. Все, що потрібно знати про libuv, я описав у своїй статті «Фундамент для JavaScript-розробника: як відповісти, що таке libuv на співбесіді з Node.js».

Тож зараз ми розглянемо, що всередині Event Loop:

Фази — те, про що далеко не всі знають або говорять, але знання фаз і є фундаментом для розуміння послідовності виконання коду, написаного на JavaScript.

2 Розкажіть про фази

  • Timers: фаза, в якій виконуються колбеки, заплановані setTimeout() і setInterval().
  • Pending callbacks: виконує I/O-колбеки, які були відкладені до наступної ітерації циклу.
  • Idle, prepare: використовувати тільки внутрішньо.
  • Poll: отримання нових подій I/O; виконувати колбеки, пов’язані з I/O (майже всі, за винятком колбеків, які виконуються в фазі close callbacks, запланованих таймерами та setImmediate()); при необхідності node може тут блокуватися.
  • Check: тут викликаються setImmediate() callbacks.
  • Сlose callbacks: закриває колбеки такі як socket/http/eventEmitter/.on(‘close', () =>).

З повною інформацією про фази можна ознайомитися тут.

3Що таке мікро- та макрозадачі

Тож після запитань «що таке Event Loop» і «що ви знаєте про фази»  запитують, чи знаєте ви, що таке мікрозадачі та макрозадачі, у відповідь на це запитання у мене також є стаття.

А зараз ми розберемо наступне:

  • різницю між setTimeout() i setImmediate();
  • різницю між process.nextTick() і setImmediate();
  • які труднощі можливо вирішити за допомогою process.nextTick().

4У чому різниця між setTimeout() i setImmediate()

setTimeout() — колбек, який ми передаємо в таймер, виконується після певного пройденого часу, переданого другим аргументом в setTimeout() або при відсутності вказаного часу, за замовчуванням через 4 мс.

setImmediate() виконується після поточної poll-фази:

const fs = require('fs');

fs.readFile(__filename, () => {
  setTimeout(() => {
    console.log('Timeout');
  }, 0);
  setImmediate(() => {
    console.log('Immediate');
  });
});

Результат:

Immediate
Timeout

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

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

setTimeout(() => {
  console.log('timeout');
}, 0);
setImmediate(() => {
  console.log('immediate');
});

В іншому випадку таймери будуть виконуватись непередбачувано. Нижче результат двух запусків таймерів:

Immediate
Timeout
Timeout
Immediate

5У чому різниця між process.nextTick() і setImmediate()

В цій ситуації завжди першим виконується process.nextTick(), він виконується при наступному тіку (tick) ядра вашого комп’ютера, а це 100-1000 тіків за секунду — і в цьому його небезпека.

Якщо ви написали рекурсивну функцію і там є process.nextTick(), то поточний цикл Event Loop так може і не завершитись, про це є застереження в офіційній документації.

6Які труднощі можливо вирішити за допомогою process.nextTick()

Є такі ситуації, коли нам треба виконати нашу функцію з мінімальною затримкою лише після того, як код буде ініціалізовано, але ще жодна I/O-операція ще не буде виконана, і тут process.nextTick() допоможе нам з легкістю:

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {
  constructor() {
    super();

    process.nextTick(() => {
      this.emit('event');
    });
  }
}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});

Цей приклад коду з офіційної документації, і дуже простий, але він зрозуміло і коротко показує нам яку важливу проблему ми можемо вирішити:

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {
  constructor() {
    super();
    this.emit('event');
  }
}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});

Якщо виключити process.nextTick() з нашого прикладу, то подія event ніколи не спрацює, тому що виклик події відбувся ще у конструкторі класу MyEmitter, а реєстрація події — пізніше.

Висновок

В мене з досвіду були кандидати з інших країн, які на запитання «що таке Event Loop» відповідали так: «Навіщо ви ставите мені таке елементарне запитання, я людина з досвідом 5+ років, і клієнт за такі знання не платить, він платить за фічі».

Звичайно, всі платять за функціонал, тільки ось цікаво, скільки буде витрачено часу і яка буде якість коду, якщо ти не знаєш, як все працює та яка сила є в наших руках.

Знання таких речей як фази і робота з ними допомагає нам розуміти більш проблемні місця в коді, писати код більш осмислено та вирішувати більш нетривіальні задачі без «милиць», що впливає на надійність і впевненість в роботі нашої системи.

Дякую вам за увагу і продуктивного кодування 😉

Якщо ви знайшли помилку, будь ласка, виділіть фрагмент тексту та натисніть Ctrl+Enter.

Останні статті

Чому написання ідеального коду може призвести до вашого звільнення

Блогер та розробник Джозеф Круз розповів, чому не варто писати ідеальний код та чому це…

18.04.2025

ChatGPT, моторошна долина та трохи Фройда

Днями я завзято нила про щось ChatGPT (експериментую між сеансами з живим терапевтом). І от…

17.04.2025

Я прийшла за покупками, а не крутити колесо

«Крутіть колесо, щоб отримати знижку до 50%!» «Натисніть тут, щоб відкрити таємничу пропозицію!» «Зареєструйтесь зараз,…

16.04.2025

Майже навайбкодив десктопний монітор CI пайплайнів

Дуже хочеться робити якісь десктопні апки. Сумую за часами коли всі програми були offline-first, і…

15.04.2025

Як працюють транзакційні комісії в мережах Bitcoin і Ethereum

Надсилаючи криптовалюту, багато новачків ставлять запитання: як працюють комісії та чому вони відрізняються в різних…

14.04.2025

Обережно, тепер вас можуть обдурити на співбесіді з роботодавцем

Нова афера набирає обертів — ось детальний розбір того, як фальшиві потенційні роботодавці намагаються вкрасти…

11.04.2025