2016-05-19 2 views
1

У меня есть некоторые недоумения относительно nodejs темы.Некоторая путаница в отношении нитей nodejs

Насколько я знаю, nodejs работает в одном потоке. Если функция async вызывается, то nodejs создаст новый поток для запуска этого асинхронного кода. После завершения асинхронного кода. event loop получит асинхронный результат и вызовет функцию обратного вызова в другом новом потоке.

Для того, чтобы проверить, я провел следующий тест-код:

var fs = require("fs"); 

fs.readFile('package.json','utf-8', function (err, data) { 
    if(err) 
     console.log(err) 
    else 
     console.log(data); 
}); 

console.log("before loop"); 
while(true); 
console.log("after loop"); 

мой ожидается результат является:

до того цикла
- - package.json контент - -

Собственно прибудете:

до того цикла

Я могу ошибаться в некоторых местах.

Вопрос:

  1. почему while(true) заблокирован readFile() или блокированы `s функции обратного вызова?
  2. Какая связь между этими потоками?
+0

Магия обратных вызовов работает из-за закрытий. Когда вы передаете функцию 'readFile', она сохраняет эту функцию в активном состоянии и сохраняет все переменные, захваченные в закрытии. Позже узел может внезапно вызвать эту функцию (при условии, что вы вернулись в цикл событий узла), и с точки зрения программиста это очень удобно, потому что закрытие имеет переменные между вызовами. Вы можете вернуться из этого образца кода, который вы показали, потому что любые необходимые переменные останутся в живых и будут доступны из любых функций, которые в них нуждаются. – doug65536

ответ

6

Вы правы в том, что nodejs работает в одном потоке. Вы можете начать отдельные процессы и поставить балансировку нагрузки перед этими процессами, чтобы использовать многоядерные процессоры, но это не реализовано в самом узле.

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

В вашем примере while (true) блокирует цикл событий, потому что это не вызов функции асинхронного вызова. Не забывайте, что не все в javascript является асинхронным - только вызовы функций могут быть асинхронными, а не другими языковыми конструкциями, такими как циклы или условные обозначения. Таким образом, в вашем примере вы запускаете асинхронный файловый ридер, который добавляется в цикл событий и запускается. Хотя файловая система делает это, цикл событий не имеет ничего общего и переходит к сообщению console.log («before loop»). После этого вы блокируете цикл событий с while (true). Это означает, что цикл событий не может переместить его на удержание и больше перейти к файлообменнику.

Надеюсь, что это прояснит ситуацию.Основной вывод здесь заключается в том, что не все в javascript является или должно быть асинхронным, но большинство трудоемких операций, связанных с различными устройствами, такими как файловая система или сеть, реализованы неблокируемым способом. Функция Async имеет смысл только тогда, когда использует какой-то внешний компонент - вы бы не использовали функцию async square root, поскольку она блокировала бы цикл событий одинаково. Это причина, по которой node.js не рекомендуется для тяжелых вычислительных операций, таких как кодирование аудио/видео. Преимущество async просто не имеет смысла.

+0

Спасибо, Тадас. Вы имеете в виду, что мой код, который не находится в функции async, будет выполняться синхронно в 'event-loop', а вызванная функция async будет выполняться асинхронным способом в' event-loop'? –

+0

Что я имею в виду, так это то, что while (true) является синхронной операцией, которая не может быть завершена или приостановлена, поэтому цикл событий не имеет возможности вернуться к filerader, и программа зависает. Для синхронных/асинхронных функций нет отдельных циклов событий, все они находятся в одном домене. –

0

Я нашел некоторые другие удивительные ответы здесь:

Вызывающий этой функции обратного вызова служит в качестве исходного кадра в стеке вызовов, а также из-за JavaScript быть однопоточный, дальнейший опрос и обработка сообщений останавливаются в ожидании возврата всех вызовов в стек. Последующие (синхронные) вызовы функций добавляют в стек новые кадры вызова (например, функция init вызывает функцию changeColor).

Это снова решило мое замешательство! Теперь я более ясен!

Смежные вопросы