Как неблокирующий ввод-вывод работает с каналами

Я хочу знать, как движок в node.js узнает, когда вызывать и выполнять операцию в очереди. Я понимаю, что node.js является однопоточным и использует асинхронную неблокировку для выполнения операций.

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

Или он выполняет поставленную в очередь операцию в конце программы. Этого не может быть. Поэтому мне любопытно узнать, что происходит под капотом и как сервер узла узнает, когда выполнять операцию в очереди.


person Community    schedule 08.05.2018    source источник
comment
Когда вы говорите о каналах, о чем именно вы говорите? Канал не является известной концепцией node.js, поэтому нам нужно знать, что вы подразумеваете под этим.   -  person jfriend00    schedule 08.05.2018
comment
Из того, что я прочитал в Интернете, неблокирующий ввод-вывод работает с каналами, поток может читать/записывать часть данных в каналах, не блокируя ввод-вывод для остальных данных.   -  person    schedule 08.05.2018
comment
В node.js нет концепции каналов — по крайней мере, это не тот термин, который node.js использует сам по себе. Не уверен, где вы это прочитали или что они имели в виду.   -  person jfriend00    schedule 08.05.2018
comment
В этом руководстве речь идет о Java, а не о Javascript. Ничего общего с node.js.   -  person jfriend00    schedule 08.05.2018
comment
Я считаю, что концепция должна быть аналогичной и в javascipt. Так разве неблокировка — это концепция, и она должна применяться ко всем доменам?   -  person    schedule 08.05.2018
comment
Не совсем. Концепция каналов в этом руководстве — это то, что библиотека реализует сама. Это не общая концепция, имеющая некоторую аналогию в node.js. Потоки ввода-вывода регулярно используются в node.js, но я не думаю, что они являются прямой аналогией этих каналов. Существует множество различных способов реализации неблокирующего ввода-вывода. Сам node.js использует несколько различных внутренних механизмов для разных типов ввода-вывода.   -  person jfriend00    schedule 08.05.2018


Ответы (2)


Непонятно, что вы подразумеваете под «каналами», поскольку это не встроенная концепция node.js или термин, который используется внутри для описания того, как работает node.js. В руководстве, на которое вы ссылаетесь в своем комментарии, речь идет о языке Java, а не Язык Javascript, поэтому он не имеет абсолютно никакого отношения к node.js. Концепция «каналов» в этом руководстве — это то, что конкретная библиотека NIO реализует в Java.

Но если вы действительно просто спрашиваете, как работают асинхронные операции в node.js, я могу объяснить эту общую концепцию.

node.js работает с очередью событий. Интерпретатор node.js захватывает следующее событие в очереди событий и выполняет его (обычно это включает вызов функции обратного вызова). Эта функция обратного вызова работает (однопоточная) до тех пор, пока не вернется. Когда он возвращается, интерпретатор node.js ищет следующее событие в очереди событий. Если они есть, он захватывает это следующее событие и вызывает связанный с ним обратный вызов. Если в настоящее время в очереди событий нет событий, то он ожидает, пока событие будет помещено в очередь событий (если нечего ожидать, возможно, запустится какая-то сборка мусора).

Теперь, когда вы запускаете какую-то асинхронную операцию в своем Javascript (например, запрос к базе данных), вы можете использовать функцию запроса к базе данных, которая инициирует запрос (путем отправки запроса в базу данных), а затем немедленно возвращается. Это позволяет вашей части Javascript, которая запустила этот запрос, затем вернуться и вернуть управление node.js.

Между тем, какой-то собственный код управляет подключением к вашей базе данных. Когда ответ возвращается из базы данных, событие добавляется во внутреннюю очередь событий node.js.

Всякий раз, когда интерпретатор node.js заканчивает выполнение другого Javascript, он просматривает очередь событий, извлекает следующее событие и вызывает связанный с ним обратный вызов. Таким образом, результат вашего запроса к БД обрабатывается вашим кодом. Во всех случаях здесь с асинхронной операцией связан некий вид обратного вызова, который интерпретатор может вызвать, когда находит событие в очереди событий.

Будучи однопоточным, он хранит данные в каналах (если я не ошибаюсь).

В node.js нет концепции «каналов», поэтому я не уверен, что вы имели в виду.

Или он выполняет поставленную в очередь операцию в конце программы.

Когда результат возвращается из базы данных, некоторый собственный код, управляющий этим, вставит событие в очередь событий node.js. Интерпретатор Javascript обработает это событие, а затем в следующий раз вернется к циклу обработки событий (другой Javascript завершил работу, и пришло время проверить следующее событие для обработки).

Важно понимать, что запуск асинхронной операции не блокируется, поэтому вы получите следующее:

console.log("1");
callSomeAsyncFunction(someData, (err, data) => {
    // this callback gets called later when the async operation finishes
    // and node.js gets a chance to process the event that was put
    // in the event queue by the code that managed the async operation
    console.log("2");
});

// right here there is nothing else to do so the interpreter returns back
// to the system, allowing it to process other events
console.log("3");

Из-за неблокирующего характера вещей это будет регистрировать:

1
3
2

Некоторые другие ссылки по теме:

Как JavaScript обрабатывает ответы AJAX в фоновом режиме?

Где находится очередь событий node.js?

Обратные вызовы

Почему цикл while блокирует узел цикл событий?

person jfriend00    schedule 08.05.2018
comment
очередь событий такая же, как стек вызовов - person ; 08.05.2018
comment
@Duck_dragon - Нет. Стек вызовов сильно отличается. Очередь событий — это буквальная очередь событий, ожидающих вызова своего обратного вызова. - person jfriend00; 08.05.2018
comment
@Duck_dragon - обновил мой ответ, добавив небольшую информацию о конкретной библиотеке/учебнике, на который вы ссылались. - person jfriend00; 08.05.2018
comment
Я обязательно рассмотрю предоставленные вами ресурсы. Спасибо. Под очередью событий подразумевают очередь задач, из которой просмотр событий проверяет, пуст ли вызов satck, а затем помещает из очереди событий в стек вызовов для выполнения. - person ; 08.05.2018
comment
@Duck_dragon — стек вызовов используется для отслеживания вызовов функций и управления возвратами функций. Когда обратный вызов из события завершен, последняя функция return вернется обратно в подсистему цикла событий, которая первоначально вызывалась. В этот момент стек вызовов теперь пуст, и система знает, что предыдущее событие выполнено, и node.js может затем получить следующее событие и вызвать его обратный вызов. Нет проверки, пуст ли стек вызовов. Когда обратный вызов события возвращается обратно в подсистему событий, стек вызовов в этот момент по определению пуст. - person jfriend00; 08.05.2018

Node внутренне использует базовые операционные системы, не блокирующие API-интерфейсы ввода-вывода. См. раздел overlapped io. , WSAEventSelect для Windows, select для Linux.

person Tamas Hegedus    schedule 08.05.2018