我需要将基本客户端和本地客户端与MQTT同步。如果客户发布,则另一方将收到消息。
如果我的MQTT代理关闭,则需要停止发送消息,将消息保存在某个地方,等待连接,然后继续发送。
如果我的本地或基本客户端关闭一秒钟,我需要保存未发送的消息,然后在打开我的基本/本地客户端时发送它。
我正在使用Node.js,无法弄清楚如何实现。
这是我与MQTT服务器连接或断开连接时的处理程序。
client.on('connect',()=>{
store.state = true;
run(store).then((value)=>console.log('stop run'));
});
client.on('offline',()=>{
store.state = false;
console.log('offline');
});
这是我的run
函数。我使用store.state
决定是否应该停止此间隔。但是这段代码似乎并不是实现我的概念的好方法。
function run(store) {
return new Promise((resolve,reject)=>{
let interval = setInterval(()=>{
if (!store.state) {
clearInterval(interval);
resolve(true);
}
else if (store.queue.length > 0) {
let data = store.queue.pop();
let res = client.publish('push',JSON.stringify(data),{qos:2});
}
},300)
});
}
我应该怎么做才能实现始终发送,在“断开连接”时停止,然后在连接后继续发送的功能?
答案 0 :(得分:0)
我认为设置300ms间隔不是很好。
如果您希望某些东西“总是运行”,则应按设置的时间间隔并且尽管循环内有任何错误,但setInterval()
是有意义的。没错,可以比“每300毫秒一次”清除更快的邮件。
自MQTT.js has a built-in queue起,您可以通过使用它进行很多简化。但是,您的消息将发布到称为“推送”的目标,因此我想您希望它们按照队列的顺序进行传递。这个答案排在队列中,着重于在确认最后一条消息后立即发送下一条消息。
如果res = client.publish(..)为false怎么办?
好点!如果要确保它到达,最好在发布成功后将其删除。为此,您需要检索值而不删除它,并使用callback参数找出发生了什么(publish()
是异步的)。如果那是唯一的更改,则可能看起来像这样:
let data = store.queue[store.queue.length - 1];
client.publish('push', JSON.stringify(data), {qos:2}, (err) => {
if(!err) {
store.queue.pop();
}
// Ready for next publish; call this function again
});
扩展它以包括基于回调的运行:
function publishFromQueue(data) {
return new Promise((resolve,reject)=>{
let res = client.publish('push', JSON.stringify(data), {qos:2}, (err) => {
resolve(!err);
});
});
}
async function run(store) {
while (store.queue.length > 0 && store.state) {
let data = store.queue[store.queue.length - 1];
let res = await publishFromQueue(data);
if(res) {
store.queue.pop();
}
}
}
这应该尽快传递所有排队的消息,而不会阻塞。唯一的缺点是它不能持续运行。您有两种选择:
run()
,例如:let isRunning = false; //Global for tracking state of running
function queueMessage(data) {
store.queue.push(data);
if(!isRunning) {
isRunning = true;
run(store);
}
isRunning = false;
}
只要您可以使用它而不是将其推送到队列,它的长度就应该相近,并且更加直接和有效。