通过expressjs将stdout从子进程流式传输到浏览器

时间:2013-12-03 17:00:34

标签: node.js express stream child-process

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

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

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

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

2 个答案:

答案 0 :(得分:13)

Express路由的响应对象也是可写流的实例,因此允许您将子进程'stdio流传递给响应。

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

答案 1 :(得分:3)

另一种方法是使用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>
&#13;
&#13;
&#13;