[英]How can I use socket.io to emit data to client-side whenever a variable change its values in server-side?
背景
我正在使用rpio
将raspberry
用作我的应用程序的服务器,同时我希望能够使用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
循环的同步for
而socket.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.