В узлах.js, как использовать дочерний процесс.exec то есть все может происходить асинхронно?


У меня есть сервер, построенный на узле.JS. Ниже приведена одна из функций обработчика запросов:

var exec = require("child_process").exec

function doIt(response) {

    //some trivial and fast code - can be ignored

    exec(
        "sleep 10",  //run OS' sleep command, sleep for 10 seconds
        //sleeping(10), //commented out. run a local function, defined below.
        function(error, stdout, stderr) {
            response.writeHead(200, {"Content-Type": "text/plain"});
            response.write(stdout);
            response.end();
    });

    //some trivial and fast code - can be ignored
}

Между тем, в том же файле модуля определена локальная функция "sleeping", которая, как следует из ее названия, будет спать в течение 10 секунд.

function sleeping(sec) {
    var begin = new Date().getTime();
    while (new Date().getTime() < begin + sec*1000); //just loop till timeup.
}

Вот три вопроса --

  1. Как мы знаем, узел.js является однопроцессорным, асинхронным, управляемым событиями. Верно ли, что все функции с аргументом обратного вызова являются асинхронными? Например, если у меня есть функция my_func (callback_func), который принимает другую функцию в качестве аргумента. Есть ли какие-либо ограничения на callback_func или где-то сделать my_func асинхронным?

  2. Так, по крайней мере, child_process.exec асинхронен с анонимной функцией обратного вызова в качестве аргумента. Здесь я передаю "sleep 10" в качестве первого аргумента, чтобы вызвать команду ОС sleep и подождать 10 секунд. Он не будет блокировать весь процесс узла, то есть любой другой запрос, отправленный другому обработчику запроса, не будет заблокирован как длиной до 10 секунд обработчиком" doIt". Однако, если сразу же на сервер отправляется другой запрос, который должен быть обработан тем же обработчиком" doIt", будет ли он ждать окончания предыдущего запроса" doIt"?

  3. Если я использую вызов функции sleeping(10) (закомментированный) для замены "sleep 10", я обнаружил, что он блокирует другие запросы до 10 секунд после этого. Может ли кто-нибудь объяснить, в чем разница?

Огромное спасибо!

-- Обновление по запросу --

Один комментарий говорит, что этот вопрос казался дубликатом другого ( Как promisify Node child_process.exec и child_process.функции execFile с Bluebird?), который был задан через год после этого.. Ну, они слишком разные - это было предложено для асинхронного в целом с конкретным случаем багги, в то время как тот спрашивал об объекте Promise per se. И намерения, и варианты использования различны.

(если они случайно похожи, не должен ли новый помечен как дубликат старого?)

1 2

1 ответ:

1) Нет. Например .forEach синхронно:

var lst = [1,2,3];
console.log("start")
lst.forEach(function(el) {
    console.log(el);
});
console.log("end")
Является ли функция асинхронной или нет, зависит исключительно от реализации-ограничений нет. Вы не можете знать его априори (вы должны либо протестировать его, либо знать, как он реализован, либо прочитать и поверить в документацию). Есть даже больше, в зависимости от аргументов функция может быть либо асинхронной, либо синхронной, либо и той, и другой.

2) нет. Каждый запрос будет порождать отдельный процесс "сна".

3) это потому что ваша функция sleeping - это полный беспорядок-это вообще не сон. Что он делает, так это использует бесконечный цикл и проверяет дату (таким образом, используя 100% процессора). Начиная с узла.js является однопоточным, то он просто блокирует весь сервер-потому что он синхронный. Это неправильно, не делай этого. Вместо этого используйте setTimeout.