【问题标题】:nodejs concurrency synchronous executionnodejs并发同步执行
【发布时间】:2018-07-29 11:21:05
【问题描述】:

我有两个 WebSocket 异步获取数据,每次我从套接字获取一些消息时,我都会在 CompareData 中执行一些代码。

问题是 CompareData 应该同步执行,或者(更好)只有在它还没有运行时才执行

这是我的代码:

function CompareData(data) {
    console.log('data ', data);
    AsyncFunction();
};
ws1 = new WebSocket(WS1_URL);
ws2 = new WebSocket(WS2_URL);
ws1.on('message', (data) => {
    CompareData(data);
});
ws2.on('message', (data) => {
    CompareData(data);
});

你能帮帮我吗?我对 NodeJs 很陌生

【问题讨论】:

  • 强制异步函数同步几乎从来都不是一个好主意。您能否详细说明您希望实现这种行为的原因?

标签: node.js asynchronous websocket synchronization


【解决方案1】:

我的建议是:

  1. 首先,您需要知道 CompareData 何时完成。重新组织您的代码以使用承诺或回调。如果您使用的是第三方异步函数,我几乎可以肯定他们会在完成时提供一些反馈 - 这是异步世界中必须具备的
  2. 在某处添加inProgress = false 标志作为简单的锁。正如有人发布的那样,JS 是单线程的,您可以保证您的代码在运行过程中不会被中断。多亏了这一点,您可以使用非常简单的锁,而不是多线程中已知的复杂的基于操作系统的互斥锁 语言。
  3. ws.on(...) 中检查是否设置了inProgress。如果没有,将其锁定并运行 CompareData
  4. 在 CompareData 完成回调中或在承诺解决方案中将 inProgress 设置回 false,因此您不再忽略传入的数据。

如果您可以简单地丢弃数据,则无需使用额外的队列、互斥锁等使这种情况复杂化。

如果您需要全部提供,则将传入数据排队并在完成回调触发后提供下一个。

这基本上是 Rahul 的建议,但他使用了当前版本标准中未建立的功能,因此如果您不转译代码,请不要使用它。

【讨论】:

    【解决方案2】:

    您应该使用一些互斥锁以避免compareData 的两个异步操作同时执行,例如node-mutexmutexify

    【讨论】:

      【解决方案3】:

      您不应该在 node.js 中进行同步调用,但可以使这些调用顺序进行。请参阅下面的示例可能会有所帮助。

      var messages = [];
      var inProgress = false;
      
      function CompareData(data) {
        return new Promise((resolve, reject) => {
          // do some stuff and resolve
          setTimeout(() => {
            resolve(data);
          }, 1000);
        });
      };
      
      const start = async () => {
        if (!inProgress) {
          if (messages.length !== 0) {
            inProgress = true;
            try {
              const data = await CompareData(messages.shift());
              console.log(data);
            } catch (error) {
              console.log(error);
            }
            inProgress = false;
            await start();
          }else{
            console.log('Process Done');
          }
        }
      }
      
      const handler = (data) => {
        messages.push(data);
        start();
      }
      
      handler(1);
      handler(2);
      handler(3);
      handler(4);
      
      // ws1 = new WebSocket(WS1_URL);
      // ws2 = new WebSocket(WS2_URL);
      // ws1.on('message', handler);
      // ws2.on('message', handler);

      【讨论】:

      • 感谢您的代码,如果在 CompareData 中也有异步函数,此示例是否有效?
      • CompareData 是异步的,那么只有你必须这样做,否则你可以直接调用。默认是同步的。
      • 如果我选择你的方法,从套接字接收的消息被放入队列中......我应该跳过 CompareData 运行时收到的所有消息;请考虑 CompareData 执行异步操作,完成执行可能需要 5 秒。只有当 CompareData 完成后,我才应该开始重新考虑来自套接字的消息。
      • 在这种情况下,您不必维护队列,您可以简单地检查 inProgress 标志是否为真,如果为假则跳过然后处理。
      • 谢谢,我对 Promise 以及与 await 和 async 相关的任何事情都不太实际...我正在测试新代码,希望它能完美运行
      【解决方案4】:

      Node.js 是单线程的。因此,您不会像在其他语言中那样真正遇到 Node 程序中发生的真正并发问题。在您的示例中,在任何给定时间最多只能发生一个用于 CompareData 的 WebSocket 回调。

      【讨论】:

      • 只要CompareData()里面没有异步函数。
      • CompareData 里面有异步函数
      • 对,那些内部异步函数在 CompareData 返回之后被调用。一次只会发生一个回调。你能详细说明你真正想要防范的事情吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-09
      • 1970-01-01
      • 2017-11-14
      • 2017-12-26
      • 2018-07-24
      • 2019-09-24
      • 1970-01-01
      相关资源
      最近更新 更多