简体   繁体   English

如何使用 socket.io 在客户端(网络浏览器)中显示来自 node.js 服务器的实时数据?

[英]How to use socket.io to display realtime data in the client (web browser) from the node.js server?

I want to display the real-time speech to text data in the browser.我想在浏览器中显示实时语音到文本数据。 By real-time what I mean is, "while I am speaking I am getting the text output simultaneously" .实时我的意思是, “当我说话时,我同时收到文本 output” I have implemented the speech-to-text part in Python using the Google cloud service API.我已经使用 Google 云服务 API 在 Python 中实现了语音转文本部分。 Then I used "child process" to run my python program in the node.js environment.然后我使用“子进程”在 node.js 环境中运行我的 python 程序。 Till now everything is fine.直到现在一切都很好。 Next, I want to display the real-time text in the browser.接下来,我想在浏览器中显示实时文本。 In another word, I want to send the real-time text output from the python (which is now running in node.js using the child process) to the web browser. In another word, I want to send the real-time text output from the python (which is now running in node.js using the child process) to the web browser. I was trying to do that with socket.io.我试图用 socket.io 做到这一点。 Here is my server side (node.js) code where socket.io is also applied:这是我的服务器端(node.js)代码,其中还应用了 socket.io:

const express = require('express');
//const router = express.Router();
const {spawn} = require('child_process');
const path = require('path');
const app = express();
const http = require('http');
const server = http.createServer(app);
//const server = http.createServer(app); 
const { Server } = require("socket.io");
const io = new Server(server);

function runScript(){
  return spawn('python3', [
          "-u",
    path.join(__dirname, 'script.py')
  ]);
}

const subprocess = runScript()


// print output of the script

app.get('/', (req,res) => {

        res.sendFile(__dirname + '/index.html');
});

io.on('connection', (socket) => {

subprocess.stdout.on('data', (data) => {
  //console.log(`data:${data}`);
        socket.on('message', (data) => {
                socket.broadcast.emit('message', data);
        });
});
});

server.listen(3000, () => {
  console.log('listening on *:3000');
});

Above, I am first using the child process to call the python program in node.js and then I am using socket.broadcast.emit to send the text output of the python program to my client side. Above, I am first using the child process to call the python program in node.js and then I am using socket.broadcast.emit to send the text output of the python program to my client side. The client-side code looks like this:客户端代码如下所示:

<!DOCTYPE html>

<html>
        <head>
        <script src="/socket.io/socket.io.js"></script>
        <script>
                var socket = io();

        var messages = document.getElementById('messages'); 

        //const EventEmitter = require('events');
        //const emitter = new EventEmitter()
        //emitter.setMaxListeners(50)
        socket.on('messages', function(data) {
                
                 document.querySelector("#style1".innerHTML = `<p>${data1}</p>`
               
        });
        </script>
        </head>

        <body id="messages">
                <h1> This is crazy </h1>
                <div id="style1">
                </div> 

        </body>

</html>

Above, I want to display the real-time text output from the python program inside the <p> tag.上面,我想在 <p> 标签内显示来自 python 程序的实时文本 output。 The problem is, I am not able to get anything in the web browser.问题是,我无法在 web 浏览器中获取任何内容。 My objective is, I want to display whatever I am speaking as text in the web browser in real-time.我的目标是,我想在 web 浏览器中实时显示我所说的任何内容。

I don't know much about socket.io.我不太了解 socket.io。 In fact, this is the first time I am using this technology.事实上,这是我第一次使用这项技术。

Your Node.js server will act as the socket server.您的 Node.js 服务器将充当套接字服务器。 As your code shows, it listens on a port for a socket connection, and on connection, creates a socket, which you then send messages too.正如您的代码所示,它在端口上侦听套接字连接,并在连接时创建一个套接字,然后您也可以发送消息。 From a simple cursory review, the server code looks okay.从一个简单的粗略审查来看,服务器代码看起来还不错。

On your webpage, you are creating the socket, and listening for messages.在您的网页上,您正在创建套接字并侦听消息。

However the socket running on the webpage hasn't yet connected to the server, which is why nothing is working yet.但是,网页上运行的套接字尚未连接到服务器,这就是为什么还没有任何工作的原因。

Assuming you're doing this on localhost, just add the socket server address to it's constructor, and then listen for connect.假设您在 localhost 上执行此操作,只需将套接字服务器地址添加到它的构造函数,然后侦听连接。

const socket = io('ws://localhost:3000');

socket.on('connect', () => {
  // do any authentication or handshaking here.
  console.log('socket connected');
});

More advanced implementations should gracefully handle closing sockets.更高级的实现应该优雅地处理关闭 sockets。

Per the following comment:根据以下评论:

I added the lines you suggested above.我添加了您在上面建议的行。 Even now nothing is visible on the webpage but I am getting this warning: (node:14016) MaxListenersExceededWarning: Possible EventEmitter memory leak detected.即使现在网页上什么也看不到,但我收到了这个警告:(节点:14016)MaxListenersExceededWarning:检测到可能的 EventEmitter memory 泄漏。 11 message listeners added.添加了 11 个消息侦听器。 Use emitter.setMaxListeners() to increase limit使用emitter.setMaxListeners() 增加限制

Looking more closely at your server code, I believe this is the root issue更仔细地查看您的服务器代码,我相信这是根本问题

subprocess.stdout.on('data', (data) => {
  //console.log(`data:${data}`);
        socket.on('message', (data) => {
                socket.broadcast.emit('message', data);
        });
});
});

Each time you receive data from subprocess.stdout , you are adding a new onmessage event handler to your socket, so after a period of time, you have added too many event handlers.每次从 su subprocess.stdout接收数据时,都会向套接字添加一个新的onmessage事件处理程序,因此一段时间后,您添加了太多事件处理程序。

Re-write your logic so that you only add socket.on('message') once (usually after your create the socket).重新编写您的逻辑,以便您只添加socket.on('message') (通常在您创建套接字之后)。

It is also worth noting that in the above code, data from stdout is not being used, as that data variable is being redefined in a lower scope by your onmessage function.还值得注意的是,在上面的代码中,没有使用来自标准输出的data ,因为您的onmessage function 在较低的 scope 中重新定义了该data变量。 Since data is being redefined, the output of your Python program is being ignored.由于正在重新定义数据,因此您的 Python 程序的 output 将被忽略。

I think this is what you want:我认为这就是你想要的:

//echo any message you receive from the socket back to the socket
socket.on('message', (data) => {
  socket.broadcast.emit('message', data);
});

//send data from std out to the socket.
subprocess.stdout.on('data', (data) => {
  //console.log(`data:${data}`);
   socket.broadcast.emit('message', data);      
});

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

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