1

我的 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);
          }
        }

      });
4

1 回答 1

4

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

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

如果你使用一个async函数,那么确保try/catch你里面的一切await,因为否则,如果任何等待的拒绝,整个函数将返回一个被拒绝的 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(例如在 a 之后await,或在此处的函数的使用者处async),那么有一点很奇怪await,您不妨只.catch使用 Promises , 并完全省略asyncandtry部分,例如:

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);
}
于 2019-03-17T06:10:20.487 回答