Как мне создать неблокирующую асинхронную функцию в node.js? - PullRequest
23 голосов
/ 21 мая 2010

Как мне создать неблокирующую асинхронную функцию? Вот то, чего я пытаюсь достичь, но моя программа все еще блокируется ...

var sys = require("sys");

function doSomething() {
  sys.puts("why does this block?");
  while(true);
}

setTimeout(doSomething,0);
setTimeout(doSomething,0);
setTimeout(doSomething,0);

sys.puts("main");

Ответы [ 9 ]

34 голосов
/ 01 августа 2011

Кросс-пост от Reddit .


Назначение асинхронных функций в JavaScript немного отличается от того, что вы ищете.

Помните, что JavaScript является однопоточным - он может делать только одно за раз. Вот некоторый традиционный код блокировки:

sys.puts("Before");
sleep(10);
sys.puts("After");

В реальном веб-приложении sleep() может вместо этого быть длительным вызовом базы данных, сетевым запросом (например, ожидание данных из веб-браузера пользователя), вспомогательным инструментом или доступом к файлу.

Если вы используете блокировку вызовов, как описано выше, сервер Node.js не сможет делать что-либо еще (например, запускать другие веб-запросы) во время ожидания.

PHP и многие другие среды веб-программирования обрабатывают это, создавая абсолютно отдельные потоки для каждого запроса. Node.js использует функции обратного вызова. Вместо этого вы можете написать такой же код:

sys.puts("Before");
setTimeout(function(){
    sys.puts("After");
}, 10000);

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

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

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

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

Редко когда вам нужно блокировать работу внутри вашей программы Node.js. Если вы это сделаете, вы должны разделить эту работу на отдельный процесс (который может быть даже другой программой Node.js) или написать аддон C / C ++ , который может свободно использовать потоки.

17 голосов
/ 18 июля 2011

Вы можете выполнять асинхронный ввод-вывод только в файле node.js, используя асинхронные функции ввода-вывода, предоставляемые расширениями среды выполнения node.js или node.js, написанными на C ++. Ваш собственный код Javascript всегда синхронизирован в node.js. Асинхронный код без ввода-вывода необходим редко, и разработчики node.js решили его вообще избежать.

Существуют некоторые запутанные способы асинхронного запуска Javascript в node.js, упомянутые другими комментаторами, но node.js не предназначен для этого типа работы. Используйте Erlang, если вам нужен такой тип параллелизма, node.js предназначен только для параллельного ввода-вывода, а для параллельных вычислений он так же плох, как Python или PHP.

10 голосов
/ 21 мая 2010

Вам нужно запустить функцию блокировки в отдельном процессе.

Этот модуль может помочь: http://github.com/cramforce/node-worker

4 голосов
/ 21 мая 2010

Если вы не хотите использовать WebWorker API / node-worker, который по-прежнему очень альфа, просто создайте дополнительную программу для узлов и обменивайтесь данными по TCP или HTTP.

Это позволяет вам отправлять вашу работу в виде HTTP-вызовов или необработанных данных TCP и асинхронно ожидать HTTP-ответа / входящего TCP-ответа.

Обратите внимание, однако, что это уместно, только если ваша задача легко сериализуема.

3 голосов
/ 21 мая 2010

setTimeout не создаст новый поток, поэтому браузер все равно будет зависать в бесконечном цикле.

Вам необходимо переосмыслить структуру вашей программы.

2 голосов
/ 27 июня 2012

Вы можете сделать это, не используя дочерний процесс, используя nextTick ()

Я только что читал это объяснение на днях о nextTick ... это отличное чтение IMO

--- редактировать: старая ссылка не работает. Нашел новый прямо на StackOverflow

понимание очереди событий node.js и process.nextTick

1 голос
/ 28 мая 2014

Если я понимаю, что вы ищете, у вас есть две функции (обе принимают обратный вызов в качестве аргумента):

process.nextTick: эта функция может быть сложена, что означает, что, если она вызывается рекурсивно, она будет зацикливаться огромное (process.maxTickDepth) число раз за тик цикла событий.

или

setImmediate: эта функция намного ближе к установке времени ожидания 0 (но происходит раньше).

В большинстве случаев вы предпочитаете setImmediate.

0 голосов
/ 23 апреля 2017

Я предполагаю, что вы экспериментируете с Nodejs. Я предполагаю, что вы не пишете ни один модуль npm и не экспортируете свою функцию как асинхронную функцию. На практике вы не столкнетесь с таким случаем, если захотите выполнить какие-либо операции блокировки вфункции или обратные вызовы, которые выполняются в среде с одним потоком, пытаются использовать соответствующие модули узлов, такие как fs, для чтения файлов, запрос на сетевой запрос и модуль асинхронности, который предоставляет различные типы асинхронных операций, также помните, что вы пытаетесь выполнить процессорасинхронный прием кода - плохая идея, потому что 2HZ может выполнить миллион строк кода всего за микросекунды

Основная цель nodejs - решить проблему, которую вы задали в вопросе, который обрабатываетсяИсходный libuv для обработки асинхронных событий, я ценю ответ об использовании установленного тайм-аута, но вы не знаете, сколько времени ждать или использовать рабочий нод, это хорошо, но вы в конечном итоге будете писать много бКод масляной пластины, поэтому просто найдите модуль npm, который удовлетворит ваши потребности.

0 голосов
/ 21 мая 2010

Эта строка:

while(true);

не «блокирует», оно просто занято, навсегда.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...