可以将异步函数作为 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/catch
您 await
内部的所有内容,否则,如果等待的任何内容被拒绝,整个函数将 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,而忽略 async
和 try
完全部分,例如:
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);
}
我的 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/catch
您 await
内部的所有内容,否则,如果等待的任何内容被拒绝,整个函数将 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,而忽略 async
和 try
完全部分,例如:
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);
}