可以将异步函数作为 Websocket(ws) listerner 传递吗? (node.js 和 ws 库)

is it ok to pass asynchronous function as Websocket(ws) listerner ? (node.js and ws library)

我的 websocket 必须执行的大多数操作都是异步的,因此我将异步函数作为回调传递给 websocket 并在其中调用 await,这样做可以吗?如果不能,我还有什么选择?
编辑:这是我的消息监听器:

ws.on('message', async function (message) {
        if (message instanceof Buffer) {
          if (currentMode == prot.dataMode) {
            await appendData(sessionData,message);
          }
          else {
            console.log("error : unexpected message received");
          }
        }
        // if the message is for defining the mode of communication
        //This message is a configuration message
        else {
          message = JSON.parse(message);
          if (message[prot.modeField] == prot.confMode) {
            console.log("conf mode");
            currentMode = prot.confMode;
            await configure(sessionData,message);
          }
          //The following messages will be data
          else if (message[prot.modeField] == prot.dataMode) {
            console.log("data mode");
            currentMode = prot.dataMode;
          }

          else{
            console.log("unknown message structure : ");
            console.log(message);
          }
        }

      });

如果 没有 任何 Promise 拒绝的机会,那么是的,使用 async 函数作为处理程序是可以的。您当前的方法会奏效。

但这是不现实的。回调处理程序不 期望 一个 async 函数,如果它生成的 Promise 被拒绝,那么你会得到一个 UnhandledPromiseRejectionWarning - 一个被拒绝的 Promise 是创建,没有在任何地方处理。这是 丑陋的 - 未处理的 Promise 拒绝已被弃用,将来它们会 使您的进程崩溃 ,您 肯定会 不想。

如果您使用 async 函数,请确保 try/catchawait 内部的所有内容,否则,如果等待的任何内容被拒绝,整个函数将 return 一个被拒绝的Promise,导致了上面的问题。例如:

ws.on('message', async function (message) {
  if (message instanceof Buffer) {
    if (currentMode == prot.dataMode) {
      try {
        await appendData(sessionData,message);
      } catch(e) {
        console.log('Error', e);
      }
    }
    else {
      console.log("error : unexpected message received");
    }
  }
  // if the message is for defining the mode of communication
  //This message is a configuration message
  else {
    message = JSON.parse(message);
    if (message[prot.modeField] == prot.confMode) {
      console.log("conf mode");
      currentMode = prot.confMode;
      try  {
        await configure(sessionData,message);
      } catch(e) {
        console.log('Error', e);
      }
    }
    //The following messages will be data
    else if (message[prot.modeField] == prot.dataMode) {
      console.log("data mode");
      currentMode = prot.dataMode;
    }

    else{
      console.log("unknown message structure : ");
      console.log(message);
    }
  }
});

综上所述,虽然上面的代码 技术上 满足了您的要求,但它有点奇怪,因为您正在等待 Promises,但在等待它们之后没有做任何事情。 await.then 的语法糖,但如果您没有任何需要在 .then 中执行的逻辑(例如在 await 之后,或在消费者处async 函数),完全有 await 很奇怪,你也可以只 .catch Promise,而忽略 asynctry 完全部分,例如:

if (currentMode == prot.dataMode) {
  appendData(sessionData,message)
    .catch((e) => {
      console.log('Error', e);
    });

如果您想确保appendData仅在最后一个appendData调用完成后运行,使用Promise队列,也许是这样的:

const appendDataQueue = [];
function queueAppend(sessionData, message) {
  appendDataQueue.push({ sessionData, message });
  tryRunNext();
}
let active = false;
function tryRunNext() {
  if (active || !appendDataQueue.length) {
    return;
  }
  const { sessionData, message } = appendDataQueue.unshift();
  active = true;
  appendData(sessionData, message)
    .then(() => {
      active = false;
      tryRunNext();
    })
    .catch((err) => {
      // handle errors
      active = false;
      tryRunNext();
    });
}

然后,在 .on 处理程序中,调用 queueAppend 而不是调用 appendData(同样,不需要 async 函数):

if (currentMode == prot.dataMode) {
  queueAppend(sessionData,message);
}