Javascript 在消息之间引入延迟

Javascript 在消息之间引入延迟,javascript,node.js,mqtt,Javascript,Node.js,Mqtt,我使用Node.js。我有一个MQTT消息事件处理程序 index.js client.on('message', function (topic, message) { // calls another function my_function(topic,message); }) let client = new S7Client(plcSettings); client.on('error', console.error); async function dataFromPL

我使用Node.js。我有一个MQTT消息事件处理程序
index.js

client.on('message', function (topic, message) {
  // calls another function
  my_function(topic,message);
})
let client = new S7Client(plcSettings);
client.on('error', console.error);
 
async function dataFromPLC (){
  try {
    await client.connect();
  } catch (err){
    console.error(err);
  }
 
  try {
    // Read DB
    const res = await client.readDB(dbNr, dbVars);
    return res;
  } catch (err) {
    console.error(err);
  } finally {
    client.disconnect();
  }
}
它在接收消息时调用另一个函数
my_函数

async function my_function(topic,message) {
   const value = await dataFromPLC();
///processes the value together with message
}
使用exports.dataFromPLC=dataFromPLC从另一个文件导出并导入到我的主函数中的函数
PLCfunctions.js

client.on('message', function (topic, message) {
  // calls another function
  my_function(topic,message);
})
let client = new S7Client(plcSettings);
client.on('error', console.error);
 
async function dataFromPLC (){
  try {
    await client.connect();
  } catch (err){
    console.error(err);
  }
 
  try {
    // Read DB
    const res = await client.readDB(dbNr, dbVars);
    return res;
  } catch (err) {
    console.error(err);
  } finally {
    client.disconnect();
  }
}

当我收到单个MQTT消息或消息之间有足够的延迟时,没有问题。但是,当我收到两条MQTT消息时,它们都会调用
my_函数
,然后调用
dataFromPLC
,其间没有太多延迟。我收到一个错误,因为在第二条消息尝试再次使用连接之前,PLC连接没有足够的时间关闭。我看了不同的选择,不太确定如何解决这个问题。我能得到一些帮助吗?

您必须设置一个消息队列,以便
onMessage
只将输入放在队列中,并将其处理推迟到以后。例如,您可以使用
使队列成为承诺,然后将
作为排队操作。通过这种方式,可以保证在之前的所有处理完成之前不会启动任何处理

这是一个小演示,单击按钮可以模拟传入的消息:

let QUEUE=Promise.resolve()
函数onMessage(msg){
console.log('GOT MESSAGE',msg)
队列=队列。然后(()=>进程(msg))
}
让pause=n=>newpromise(r=>setTimeout(r,n));
异步函数进程(msg){
console.log('BEGIN',msg)
等待暂停(200);console.log('busy',msg)
等待暂停(200);console.log('busy',msg)
等待暂停(200);console.log('busy',msg)
等待暂停(200);console.log('busy',msg)
等待暂停(200);console.log('busy',msg)
console.log('END',msg)
}
msg=0
document.querySelector('button')。addEventListener('click',()=>onMessage(++msg))

message
您必须设置一个消息队列,以便
onMessage
只将输入放在队列中,并将其处理延迟到以后。例如,您可以使用
使队列成为承诺,然后将
作为排队操作。通过这种方式,可以保证在之前的所有处理完成之前不会启动任何处理

这是一个小演示,单击按钮可以模拟传入的消息:

let QUEUE=Promise.resolve()
函数onMessage(msg){
console.log('GOT MESSAGE',msg)
队列=队列。然后(()=>进程(msg))
}
让pause=n=>newpromise(r=>setTimeout(r,n));
异步函数进程(msg){
console.log('BEGIN',msg)
等待暂停(200);console.log('busy',msg)
等待暂停(200);console.log('busy',msg)
等待暂停(200);console.log('busy',msg)
等待暂停(200);console.log('busy',msg)
等待暂停(200);console.log('busy',msg)
console.log('END',msg)
}
msg=0
document.querySelector('button')。addEventListener('click',()=>onMessage(++msg))

消息
每次收到消息时,您是否都连接到数据库或断开与数据库的连接?这是个好习惯吗?我总是在开始时打开一个连接,就是这样。一次
等待client.connect()
在脚本的最开始,作业完成。这需要几秒钟,但只有一次。我应该更清楚。它通过TCP/IP连接到西门子S7 PLC。由于我不经常收到MQTT消息(一天不超过10条),我认为保持PLC连接打开是浪费。另外,我不太确定当PLC在晚上关闭并在第二天启动时,它是否会自动重新连接。所以我认为这是一个安全的方法。它能解决下一次函数调用在第一次调用之前试图从PLC读取数据的问题吗?啊啊,的确,这与我所想的完全不同。我现在甚至不知道西门子S7 PLC是什么:)您需要所有消息还是只需要每隔x个时间发送消息?如果您需要消息,例如200ms,您可以对消息处理程序进行去盎司处理,只需忽略其间的一些事件,这样您就可以每200ms至少收到一条消息(这适用于发送或接收),查找
debounce
,这在本文中是一个有用的概念。谢谢@Sebastián Espinosa。但所有信息都是唯一的,我需要记录所有信息。这些消息是在更改时生成的。您是否在每次收到消息时都连接到数据库或断开与数据库的连接?这是个好习惯吗?我总是在开始时打开一个连接,就是这样。一次
等待client.connect()
在脚本的最开始,作业完成。这需要几秒钟,但只有一次。我应该更清楚。它通过TCP/IP连接到西门子S7 PLC。由于我不经常收到MQTT消息(一天不超过10条),我认为保持PLC连接打开是浪费。另外,我不太确定当PLC在晚上关闭并在第二天启动时,它是否会自动重新连接。所以我认为这是一个安全的方法。它能解决下一次函数调用在第一次调用之前试图从PLC读取数据的问题吗?啊啊,的确,这与我所想的完全不同。我现在甚至不知道西门子S7 PLC是什么:)您需要所有消息还是只需要每隔x个时间发送消息?如果您需要消息,例如200ms,您可以对消息处理程序进行去盎司处理,只需忽略其间的一些事件,这样您就可以每200ms至少收到一条消息(这适用于发送或接收),查找
debounce
,这在本文中是一个有用的概念。谢谢@Sebastián Espinosa。但所有信息都是唯一的,我需要记录所有信息。这些消息是在更改时生成的。谢谢gerog。我试过你的建议。它似乎不起作用。我更新了我的问题,你的回答是正确的。谢谢@georg。这是一个愚蠢的错误