Що саме являє собою галочку циклу подій Node.js?


84

Я детальніше вивчаю внутрішню частину архітектури Node.js, і термін, який, як я бачу, часто зустрічається, це "галочка", як у "наступному галочці циклу подій" або функції nextTick () .

Те, чого я не бачив, - це тверде визначення того, що саме таке «кліщ». Грунтуючись на різних статтях ( таких як ця ), я зміг скласти концепцію в своїй голові, але не впевнений, наскільки вона точна.

Чи можу я отримати точний і детальний опис галочки циклу подій Node.js?


оскільки його "цикл" означає "наступний раз, коли він зациклюється", тож галочка цілий цикл, він закінчується, коли не ініціюються жодні події, і nodejs зациклював все, щоб перевірити, чи спрацьовує якесь, "nextTick" це означає наступне цикл після поточного.
Gntem

Відповіді:


156

Пам’ятайте, що, хоча JavaScript є однопотоковим, усі входи / виходи вузла та виклики власних API є або асинхронними (за допомогою механізмів, що відповідають платформі), або виконуються в окремому потоці. (Це все обробляється через libuv.)

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

Небезпечно просто викликати функцію JS з потоку, де відбулася власна подія, з тих самих причин, з якими ви стикалися б у звичайному багатопотоковому додатку - умови гонки, доступ до неатомної пам'яті тощо.

Отже, що ми робимо, це розміщуємо подію в черзі безпечним способом. У спрощеному пседокоді щось на зразок:

lock (queue) {
    queue.push(event);
}

Потім, повернувшись до основного потоку JavaScript (але на стороні C), ми робимо щось на зразок:

while (true) {
    // this is the beginning of a tick

    lock (queue) {
        var tickEvents = copy(queue); // copy the current queue items into thread-local memory
        queue.empty(); // ..and empty out the shared queue
    }

    for (var i = 0; i < tickEvents.length; i++) {
        InvokeJSFunction(tickEvents[i]);
    }

    // this the end of the tick
}

Значок while (true)(який насправді не існує у вихідному коді вузла; це суто ілюстративно) представляє цикл подій . Внутрішній forвикликає функцію JS для кожної події, яка була в черзі.

Це галочка: синхронне виклик нуля або більше функцій зворотного виклику, пов’язаних із будь-якими зовнішніми подіями. Як тільки черга вичерпається і повернеться остання функція, галочка закінчиться. Ми повертаємось на початок (наступний галочку) і перевіряємо наявність подій, які були додані в чергу з інших потоків під час роботи нашого JavaScript .

Що може додати речі до черги?

  • process.nextTick
  • setTimeout/setInterval
  • I / O (матеріали з fs, netтощо)
  • cryptoпроцесорні функції, такі як криптопотоки, pbkdf2 та PRNG (які насправді є прикладом ...)
  • будь-які власні модулі, які використовують робочу чергу libuv, щоб зробити синхронні виклики бібліотеки C / C ++ виглядають асинхронними

2
Так, ти прибив це. Копіювання черги та проходження всіх подій на копії - це те, про що я особливо цікавився. Хоча зараз багато сенсу. Дякую.
d512

Це знаменитий алгоритм "Асинхронна ітерація"?
Стеф

1
@sanjeev, що ви маєте на увазі під "звичайною роботою"? Єдине, що робить поточна програма JavaScript - це обробка подій.
josh3736

2
Я хотів би додати, що в 0.10.x setImmediateтакож додасть функцію в чергу.
DanielKhan

1
Чи означає галочка фазу циклу подій?
faressoft

10

Більш проста відповідь для початківців JavaScript:

Перше, що слід зрозуміти, це те, що JavaScript - це «однопотокове середовище». Це стосується поведінки JavaScript під час виконання блоків коду по одному з "циклу подій" в одному потоці. Нижче є елементарна реалізація циклу подій, взята з книги Кайла Сімпсона ydkJS, а потім пояснення:

// `eventLoop` is an array that acts as a queue (first-in, first-out)
var eventLoop = [ ];
var event;

// keep going "forever"
while (true) {
    // perform a "tick"
    if (eventLoop.length > 0) {
        // get the next event in the queue
        event = eventLoop.shift();

        // now, execute the next event
        try {
            event();
        }
        catch (err) {
            reportError(err);
        }
    }
}

Перший цикл while імітує цикл подій. Позначка - це скидання події з "черги циклу подій" та виконання згаданої події.

Будь ласка, перегляньте відповідь "Josh3796", щоб отримати більш детальне пояснення того, що відбувається під час скидання та виконання події.

Крім того, я рекомендую прочитати книгу Кайла Сімпсона тим, хто зацікавлений у глибокому розумінні JavaScript. Він повністю безкоштовний і з відкритим кодом, і його можна знайти за цим посиланням: https://github.com/getify/You-Dont-Know-JS

Конкретний розділ, на який я посилався, можна знайти тут: https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/sync-async/ch1.md


1

Дуже простий і короткий спосіб галочки події:

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


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