Столкнулись с трудностью остановки потока в порождении дочернего процесса в Node.js?

1

Я пытаюсь использовать Node.js Child process spawn. Ниже код выполнит определенные команды оболочки и прочитает данные как прослушиватели потоков буфера, предоставленные процессом spawn. Модуль обездвиживания узла Bluebird используется для обертывания дочернего процесса.

var execSpawn = require('child_process').spawn;
var Promise = require('bluebird');

spawnAction = function(path, cmd, cb){
return function(resolve, reject){
    cmdExec = execSpawn(path, cmd);
    var fileData = {}
    var count = 0;
    cmdExec.stdout.on('data', function(data){
        if(cb){
            fileData = data.toString('utf8');
        }else{
            if(data =='.'){
                count +=1;
            }else{
                console.log(data.toString('utf8'));
            }
        }
    });
    cmdExec.stderr.on('data', function(data){
        if(reject){
            reject("error in scrubbing "+cmd.slice(-1) + " "+data.toString('utf8'));
        }
    });
    cmdExec.on('exit', function(){
     console.log("reach the exit event");
    })
    cmdExec.on('close', function(){
        if(cb){
            resolve(cb(fileData));
        }else{
            resolve(count);
        }
    });
}

}

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

promises = []
cp = new Promise(spawnAction(Path, ['cmd'],parsingMethodHandler));
cp.then(function(data){
    data.forEach(function(disk){
       var handler = new Promise(self.spawnAction(Path, "next command"));
       promises.push(handler);
   }
}.then(function(){
    Promise.all(promises).then(function(result){
        //certain actions
    }.catch(function(err){
        //catch error specific to the failure of promise handler
    })
}).catch(function(err){
  //error specific to the first promise
    })

И моя проблема в том, что если какая-либо ошибка во время исполнения обещания, она должна достичь "cmdExec.stderr.on" и отказаться от обещания. Даже после ошибки я получаю консольные журналы, помещенные в потоки "cmdExec.stdout.on", я не мог прекратить прием потоков буфера.

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

Заранее благодарим за любые предложения или идеи.

  • 0
    Избегайте этого параметра cb . Удалите его и все его использования, и вместо этого просто вызовите cp.then(parsingMethodHandler) . Кроме того, return внутреннее обещание из обратного вызова then чтобы вам не требовались отдельные .catch() - внешнего должно хватить.
  • 0
    Почему именно у вас есть массив promises ? В вашем коде в него вставляется только одно обещание. Это ваш настоящий код?
Показать ещё 5 комментариев
Теги:
promise
child-process
bluebird

1 ответ

0

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

Мое решение - хранить весь процесс появления при создании массива. При столкновении с каким-либо одним процессом всплытия вызовет прерывание "SIGINT", чтобы немедленно уничтожить все действия. Это немедленно прекратит выполнение процесса и выбросит ошибку. Вы можете найти фрагмент кода ниже

var execSpawn = require('child_process').spawn;
var Promise = require('bluebird');

var child_process_list = []

var spawnAction = function(path, cmd, cb){
    return function(resolve, reject, onCancel){
        cmdExec = execSpawn(path, cmd);
        child_process_list.push(cmdExec);
        var fileData = {}
        var count = 0;

        cmdExec.stdout.setEncoding('utf8');
        cmdExec.stdout.on('data', function(data){
            //Certain actions with filedata and count;
            console.log(data);
        });
        cmdExec.stderr.on('data', function(data){
            while(child_process_list.length > 0){
                proc = child_process_list.pop();
                proc.kill('SIGINT');
            }
            if(reject){
                reject("error "+cmd.slice(-1) + " "+data.toString('utf8'));
            }
        });

        cmdExec.on('close', function(){
                if(cb){
                   resolve(cb(fileData));
                }else{
                    resolve(count);
                }
        });
       }
    }

var handle = function(path, cmd, cb) {
    var promises = []
    cp = new Promise(spawnAction(path, ['cmd'],parsingMethodHandler));
    cp.then(function(data){
        data.forEach(function(disk){
            cmd.push(disk);
            var handler = new Promise(self.spawnAction(path, cmd));
            promises.push(handler);
        });
    }).then(function(){
        Promise.all(promises).then(function(result){
            console.log("result => ",result);
            child_process_list = [];
            cb();
        }).catch(function(err){
            console.log("error call => ",err);
            cb();
        })
    }).catch(function(err){
        console.log("Failed in fetching drive path available ",err);
        cb()
    })     
}

Я хотел бы подтвердить свой подход и сообщить, что для решения этой проблемы доступен более эффективный подход. Заранее спасибо.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню