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

use*_*799 8 stream child-process node.js express

我们使用内置的应用程序nodejs,expresschild_process.spawn.一个要求是我们需要在运行时生成一个进程并捕获它的输出并将其呈现给用户.

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

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

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

hex*_*ide 15

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

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


AJ *_*rst 5

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

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

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

import sys

# Flush after each print to stdout
sys.stdout.flush()
Run Code Online (Sandbox Code Playgroud)

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

import sys

# Flush after each print to stdout
sys.stdout.flush()
Run Code Online (Sandbox Code Playgroud)

在客户端,你可以注册一个事件监听器:

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.');
	})
})
Run Code Online (Sandbox Code Playgroud)