繁体   English   中英

每当变量在服务器端更改其值时,如何使用socket.io将数据发送到客户端?

[英]How can I use socket.io to emit data to client-side whenever a variable change its values in server-side?

背景

我正在使用rpioraspberry用作我的应用程序的服务器,同时我希望能够使用javascript控制GPIO。 到目前为止,我是一个初学者,我只是想在html页面上显示与GPIO相关的信息。

我想做的事

我想根据碰巧在服务器端进行操作的变量在客户端进行动态更改; 换句话说,我希望每当此变量在服务器端更改其值时, socket.io会将其发送到客户端,以便我可以在paragraph标记中使用(显示)该变量的更新版本。 就我而言,我只想在页面上显示某个树莓针的高低。 我使用一个blinkLed for循环的blinkLed函数,该函数在每次迭代中打开和关闭某个引脚。

我渲染主页“/”,在那里我可以点击一个按钮来发送POST请求为“/”,然后将其呈现blinkLed页面,位于客户端的一部分socketio和我想要的显示处于段落内部的固定状态; 当此类页面加载时,socketio在服务器端执行功能blinkLed()来执行rpio技巧,从而通过rpiowrite函数将引脚置于高或低状态。 一切正常。 注意,内部的功能blinkLed()我使用socket.emit发射时的字符串“高”或“低”每次rpiowrite被称为内for循环。

app.js

var rpio = require('rpio')
var app = require('express')()
var http = require('http').createServer(app);
var io = require('socket.io')(http);

async function blinkLed(socket){
rpio.open(12, rpio.OUTPUT, rpio.LOW);
for (var i = 0; i < 5; i++) {
        /* On for 1 second */
        await rpio.write(12, rpio.HIGH);
        await rpio.sleep(1);
        await socket.emit('data','high')

        /* Off for half a second (500ms) */
        await rpio.write(12, rpio.LOW);
        await rpio.msleep(500);
        await socket.emit('data','low')

        }
}

app.set('view engine', 'ejs');

app.get("/", function(req,res){
    res.render('home')
})

io.on('connection', function(socket){
    console.log('Blink Led Page');
    blinkLed(socket)
});

app.post("/", async function(req,res){
     res.render('blinkLed');
})

http.listen(3000,'0.0.0.0',function(){
    console.log('server on')
})

blinkLed.ejs

<script src="/socket.io/socket.io.js"></script>
        <script>

        function showParagraph(data){
                return document.getElementById('p').innerHTML=data
        }
        var socket = io();
           socket.on('data', function(data){
               showParagraph(data)
        })
        </script>
<h1>BlinkLed</h1>

<p id='p'></p>
<a href='/'>Back</a>

问题

rpio功能运行良好; 问题在于,自从for循环迭代开始以来,没有显示段落,而是仅在for迭代结束之后显示某些内容。 看起来socketio仅在最后一次迭代后才向客户端发出,然后仅在迭代的最后一个循环结束后才更改段落的值。 我想在for循环的每次迭代中听听这些变化。 反正有做吗?

预先感谢您提供任何可能的帮助!

编辑:改进的问题

您的rpio.write()rpio.sleep()以及socket.emit()函数不会返回promise。 因此,与它们一起使用await根本没有什么用,因为await仅在您等待诺言时才有用。

因此,您的for循环只是for循环的同步forsocket.emit()可能实际上无法发送其数据,除非您给nodejs一些循环来处理它,这是在for循环完成之后发生的。

也可能是socket.emit()实际上正在发送数据,但是数据以如此之快的速度到达客户端,以致您永远没有机会看到屏幕更新,而您看到的只是最终更新。

rpio.sleep()函数阻止node.js Javascript线程。 正如它在rpio libirary的文档中说的那样“ sleep函数会阻塞,但很少在这些简单程序中 对此有所帮助 。如果重要,请使用setInterval()/ setTimeout()循环”。 好吧,这很重要。

因此,这里的一种解决方案是使用实际的非阻塞延迟,使每个人都有机会实际处理事物:

// utility function that returns a promise that resolves after a delay
function delay(t) {
    return new Promise(resolve => {
        setTimeout(resolve, t);
    });
}


for (let i = 0; i < 5; i++) {
    /* On for 1 second */
    rpio.write(12, rpio.HIGH);
    socket.emit('data','high')
    await delay(1000);

    /* Off for half a second (500ms) */
    rpio.write(12, rpio.LOW);
    socket.emit('data','low')
    await delay(500);
}

暂无
暂无

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

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