【问题标题】:Stream stdout from child process to browser via expressjs通过 expressjs 将标准输出从子进程流式传输到浏览器
【发布时间】:2013-12-19 20:50:09
【问题描述】:

我们有一个使用nodejsexpresschild_process.spawn 构建的应用程序。一个要求是我们需要在运行时生成一个进程并捕获它的输出并将其呈现给用户。

我们有这样的工作。但是,我们需要找到一种方法来流式传输输出,而不是等到子进程存在。

我们环顾四周,找不到任何明确的例子,想知道这里是否有人有任何想法?

一切正常。我们只是不关心在显示整个输出之前必须等待命令完成的用户体验。如果我们可以流式传输它,那将是理想的,因为触发了标准输出数据事件,浏览器将使用新数据进行更新。就目前而言,它确实是成块的,而不是一大块。所以它非常适合这样做。

【问题讨论】:

    标签: node.js express stream child-process


    【解决方案1】:

    Express 路由的响应对象也是可写流的一个实例,因此您可以将子进程的stdio 流通过管道传递给响应。

    app.get('/path', function(req, res) {
      var child = spawn('ls', ['-al']);
      child.stdout.pipe(res);
    });
    

    【讨论】:

    • 它仍在等待进程完成,然后才开始在浏览器中显示内容。不过,按照自己的方式进行操作肯定要容易得多,所以感谢您的提示。但是,它仍在等待该过程完成。
    • 这不会等到进程完成。如果看起来是这样,这意味着进程在完成之前不会向其stdout 流写入任何内容,这将是进程的问题,而不是 Node.js 的问题。在这种情况下它正在流式传输。
    • 这很奇怪,好像我绑定到 child.stdout 我按预期间歇性地接收数据。目前,我们已经实现了一种似乎有效的 socket.io 方法。它比我们想要的效果更好,但它会做到的。
    【解决方案2】:

    另一种方法是使用Socket.IO。 Socket.IO 就是为这种客户端和服务器之间基于事件的实时通信而设计的。

    关键是在写入后刷新标准输出流。这应该触发“childprocess.stdout.on('data', ...)”事件。

    如何做到这一点取决于您的子进程是用什么语言编写的。假设您正在运行 python 脚本并使用“print”写入标准输出,那么您需要这样做:

    import sys
    
    # Flush after each print to stdout
    sys.stdout.flush()
    

    这是一个使用 Socket.IO 实现您所要求的简单示例。服务器端代码:

    var app = require('express')();
    var http = require('http').Server(app);
    var io = require('socket.io')(http);
    var child = require('child_process');
    
    app.get('/', function(req, res){
      res.sendFile(__dirname + '/index.html');
    });
    
    http.listen(8000, function(){
    	console.log('listening on *:8000');
    });
    
    io.on('connection', function(socket){
    	console.log('new user connected');
    	
    	var python = child.spawn( 'python', ['compute.py'],[]);
    
    	var chunk = '';
    	python.stdout.on('data', function(data){
    		chunk += data
    		socket.emit('newdata', chunk);
    	} );
    	
    	python.stderr.on('data', function (data) {
    		console.log('Failed to start child process.');
    	})
    })

    然后,您可以在客户端上注册一个事件监听器:

    <script src="/socket.io/socket.io.js"></script>
    <script>
      var socket = io();
       
      socket.on('newdata', function(d){
         // Do something with the data
      })
    </script>

    【讨论】:

      猜你喜欢
      • 2011-04-21
      • 1970-01-01
      • 2010-10-11
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 2013-04-18
      • 2019-10-03
      相关资源
      最近更新 更多