Подтвердить что ты не робот

Node js получить и установить данные из разных процессов

У меня есть приложение node, которое выполнило запуск (дочерний процесс) и приложение, приложение имеет хост и порт:

var exec = require('child_process').spawn;
var child = exec('start app');
console.log("Child Proc ID " + child.pid)
child.stdout.on('data', function(data) {
    console.log('stdout: ' + data);
});
child.stderr.on('data', function(data) {
    console.log('stdout: ' + data);
});
child.on('close', function(code) {
    console.log('closing code: ' + code);
});

некоторое приложение начнется немедленно, и некоторое приложение займет некоторое время 10-20 секунд, пока не начнет.

Теперь я использую прокси-сервер node http для запуска приложения, и проблема в том, что Im получает сообщение об ошибке, когда приложение хочет запустить приложение до его запуска и запуска. Любая идея как-то я могу решить эту проблему?

proxy.on('error', function (err, req, res) {
    res.end('Cannot run app');
});

Btw, я не могу отправить ответ 500 в прокси-ошибке из-за ограничения нашей структуры. Любая другая идея, как я могу отслеживать приложение, возможно, с некоторым таймаутом, чтобы увидеть, как он отправляет ответ 200.

UPDATE - пример моей логики

httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({});
http.createServer(function (req, res) {
    console.log("App proxy new port is: " + 5000)
    res.end("Request received on " + 5000);
}).listen(5000);

function proxyRequest(req, res) {
    var hostname = req.headers.host.split(":")[0];
    proxy.web(req, res, {
        target: 'http://' + hostname + ':' + 5000
    });  

    proxy.on('error', function (err, req, res) {
        res.end('Cannot run app');
    });
}
4b9b3361

Ответ 1

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

proxy.on('proxyRes', function (proxyRes, req, res) {
  // Your target app is definitely up and running now because it just sent a response;
  // Use the status code now to determine whether the app started successfully or not
  var status = res.statusCode;
});

Надеюсь, что это поможет.

Ответ 2

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

Итак, в основном вам нужен обработчик http, который задерживает запрос до тех пор, пока дочерний процесс не будет готов. Так что просто сделайте ajax-вызов из html и покажите анимацию загрузки, пока служба не будет готова.

//Ajax call for each process  and update the UI accordingly   
$.get('/services/status/100').then(function(resp) {
   $('#service-100').html(resp.responseText);
})

//server side code (express syntax)
app.get('/services/status/:id ', function(req,res) {
     // Check if service is ready 
     serviceManager.isReady(req.params.id, function(err, serviceStats) {
         if(err) {
            //do logic err here , maybe notify the ui if an error occurred
            res.send(err);
            return;
         }
         // notify the ui , that the service is ready to run , and hide loader
         res.send(serviceStats);
     });
})

Ответ 3

Я не уверен, что правильно понимаю вопрос, но вы хотите дождаться, когда дочерний процесс начнет вращаться по запросу, и вы хотите, чтобы этот запрос дождался этого дочернего процесса и затем был отправлен на него? Если это так простое решение, мы будем использовать что-то вроде этого

    var count = 0;//Counter to check
    var maxDelay = 45;//In Seconds
    var checkEverySeconds = 1;//In seconds
    async.whilst(
        function () {
            return count < maxDelay;
        },
        function (callback) {
            count++;
            self.getAppStatus(apiKey, function (err, status) {
                if (status != 200) {
                    return setTimeout(callback, checkEverySeconds * 1000);

                } 
                continueWithRequest();

            });
        },
        function (err) {
            if (err) {
                return continueWithRequest(new Error('process cannot spin!'));
            }
        }
    );

Функция continueWithRequest() переадресует запрос дочернему процессу, и getAppStatus вернет 200, когда начался дочерний процесс, и какой-то другой код, когда он не является. Общая идея заключается в том, что каждый раз проверяется каждый раз, если процесс выполняется, и через 45 секунд, если нет, он вернет ошибку. Время ожидания и интервалы проверки можно легко отрегулировать. Это немного грубо, но будет работать для задержки запроса, а setTimeout запустит новый стек и не будет блокироваться. Надеюсь, это поможет.

Ответ 4

Если вы знаете (вокруг), сколько времени требуется для запуска приложения, просто добавьте setTimeout(proxyRequest, <Time it takes the app to start in MS>)

(Есть, скорее всего, более умные/сложные решения, но этот самый простой.)

Ответ 5

Почему бы не использовать событие-эмиттер или мессенджер?

var eventEmitter = require('event-emitter')
var childStart = require('./someChildProcess').start()

if (childStart !== true) {
        eventEmitter.emit('progNotRun', {
            data: data
        })
} 

function proxyRequest(req, res) {

    var hostname = req.headers.host.split(":")[0];
    proxy.web(req, res, {
        target: 'http://' + hostname + ':' + 5000
    });  

    eventEmitter.on('progNotRun', function(data) {
        res.end('Cannot run app', data);
    })
}