简体   繁体   English

难于在Node.js中的子进程生成中停止流?

[英]Facing difficulty to stop the stream in child process spawn in Node.js?

I am trying to use Node.js Child process spawn. 我正在尝试使用Node.js子进程生成。 Below code will execute the certain shell commands and read the data as buffer streams listener provided by spawn process. 下面的代码将执行某些shell命令,并将数据作为spawn进程提供的缓冲流侦听器读取。 Bluebird node promise module is used to wrap around the child process. 蓝鸟节点Promise模块用于包装子进程。

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);
        }
    });
}

} }

Above method is called multiple times for parallel execution using the following ways: 使用以下方法多次调用上述方法以并行执行:

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
    })

And my problem is if in case any error during the execution of anyone promises it should reach "cmdExec.stderr.on" and do the reject the promise. 我的问题是,如果在任何人的执行过程中出现任何错误,都应保证它应达到“ cmdExec.stderr.on”并拒绝该应许。 Even after the error am getting console logs placed inside "cmdExec.stdout.on" streams, I couldn't stop receiving the buffer streams. 即使错误使控制台日志放入“ cmdExec.stdout.on”流中之后,我也无法停止接收缓冲区流。

I would like to know is there any specific way to stop the child process execution if it faces any error and stopped by throwing the error instead of proceeding in receive the streams. 我想知道是否有任何特定的方法来停止子进程的执行,如果它遇到任何错误并通过抛出错误而不是继续接收流而停止。

Thanks in advance for any suggestions or ideas. 在此先感谢您的任何建议或想法。

Thanks for the comments and suggestions. 感谢您的评论和建议。 I figured out the way to resolve the problem of stop the Eventlistener binded to child process spawn. 我想出了一种方法来解决停止将Eventlistener绑定到子进程生成的问题。 In the above code, whenever promise.all is called and in turn fired multiple handler with spawn process created along with various listeners. 在上面的代码中,每当调用promise.all时,依次触发带有多个侦听器创建的生成进程的多个处理程序。 If one error occurred in any one of the spawn process under the promise will need to throw an error and stop all the created spawn process immediately. 如果在promise的任何一个生成过程中发生了一个错误,将需要抛出一个错误并立即停止所有创建的生成过程。

My solution is store all the spawn process during creation in an array. 我的解决方案是将创建过程中的所有生成过程存储在一个数组中。 On facing error with any one spawn process will call interrupt "SIGINT" to kill all actions immediately. 在任何一个生成过程中遇到错误时,都会调用中断“ SIGINT”以立即终止所有操作。 This stops the process execution immediately and throw the error. 这将立即停止进程执行并抛出错误。 You can find code snippet below 您可以在下面找到代码片段

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()
    })     
}

I would like to validate my approach and let me know any better approach is available to address this situation. 我想验证我的方法,并让我知道可以使用任何更好的方法来解决这种情况。 Thanks in advance. 提前致谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM