我非常怀疑我编写的代码是实现目标的有效/最佳方式。
我有一个承诺,可以进行SQL查询,完成后,我遍历一个数组及其子数组+对象。即使任何子循环由于任何特定原因而失败,我也希望内部循环继续执行,直到遍历整个数组为止。现在我有一个“ try / catch”地狱,我怀疑这是正确的方法。但是我应该说它按预期工作,但是代码有多糟糕?
new Promise((resolve, reject) => {
sqlConnection.execute(
'INSERT INTO pms (userId, message, conversationId) VALUES (?, ?, ?)',
[userid, receivedMsg, receivedConvId],
function(err, results) {
if (err) throw err;
resolve("DEBUG: PM from "+username+" into conv "+receivedConvId+" was sucessfully inserted to DB");
}
);
}).then(() => {
users.forEach(function(userobj, i, arr) {
try {
if (userobj.memberof.includes(receivedConvId)) {
let rcptUsername = userobj.username;
let rcptUserid = userobj.userid;
debug(rcptUsername+" is member of the group "+receivedConvId);
Object.keys(userobj.sessions).forEach(function(session) {
try {
userobj.sessions[session].forEach(function(wsConn) {
try {
debug("DEBUG: Broadcasting message to "+rcptUsername+" for connections inside session "+session);
wsConn.send(JSON.stringify(msgToSend));
} catch(err) {
errorHandler(err);
}
});
} catch(err) {
errorHandler(err);
}
});
}
} catch(err) {
errorHandler(err);
}
});
}).catch((err) => {
debug(err);
}).then(() => {
debug("INFO: Message broadcast finished");
});
我要遍历的数组可能看起来像这样:
[
{ username: 'Root',
userid: '1',
memberof: [ 1, 2, 3 ],
sessions:
{
pvkjhkjhkj21kj1hes5: [Array],
'4duihy21hkk1jhhbbu52': [Array]
}
},
{
username: 'Admin',
userid: '2',
memberof: [ 1, 2, 4 ],
sessions:
{
cg2iouoiuiou111uuok7: [Array],
sl1l3k4ljkjlkmmmmkllkl: [Array]
}
}
]
感谢任何建议。
答案 0 :(得分:0)
假设wsConn
是一个https://github.com/websockets/ws
网络套接字-那么您使用的代码无论如何都只会“检测”即时错误-不会捕获任何套接字写入失败
您还将在任何wsConn.send
完成之前输出“ INFO:消息广播已完成”,因为它是异步的
幸运的是,.send
有一个回调,一旦发送完成,就会在错误或成功时回调该回调-这可以解决这两个问题
使用promise是一个好主意,除了除了最初的SQL执行外,您没有对promise使用promise,这就是为什么您最终陷入了地狱
我非常有信心(没有完整的代码,我不确定)下面的代码不仅可以运行,而且嵌套少得多
new Promise((resolve, reject) => {
sqlConnection.execute(
'INSERT INTO pms (userId, message, conversationId) VALUES (?, ?, ?)',
[userid, receivedMsg, receivedConvId],
(err, results) => {
if (err) {
return reject(err);
}
resolve("DEBUG: PM from " + username + " into conv " + receivedConvId + " was sucessfully inserted to DB");
}
);
}).then(() => {
const allConnectionsArray = users
.filter(({memberof}) => memberof.includes(receivedConvId)) // filter out any userobj we aren't going to send to
.map(({rcptUsername, rcptUserid, sessions}) => {
debug(rcptUsername + " is member of the group " + receivedConvId);
const userSessionsArray = Object.entries(sessions).map(([session, value]) => {
return value.map((wsConn, index) => {
return { wsConn, rcptUserid, rcptUsername, session, index };
})
});
return [].concat(...userSessionsArray); // flatten the array
});
const promises = [].concat(...allConnectionsArray) // flatten the array
.map(({ wsConn, rcptUserid, rcptUsername, session, index }) => {
debug("DEBUG: Broadcasting message to " + rcptUsername + " for connections inside session " + session);
return new Promise((resolve) => {
wsConn.send(JSON.stringify(msgToSend), err => {
if (err) {
return resolve({ rcptUserid, rcptUsername, session, index, err });
}
resolve({ rcptUserid, rcptUsername, session, index, err: false });
});
});
});
return Promise.all(promises);
}).then(results => {
/* results is an array of {
rcptUserid
rcptUsername
session
index //(index is the ordinal position in user.sessions array
err //(===false if success)
}
*/
debug("INFO: Message broadcast finished");
}).catch(error => {
// the only error caught here would be in the `return reject(err);` in the sql execute,
// because any failure in wsConn.send is a resolved promise (with an error property)
// unless I'm not seeing something obvious, they are the only possible places an error could be thrown anyway
});