在 promise 内出错后继续子循环 - try/catch

continue sub loops after error inside promise - try/catch

我严重怀疑我正在编写的代码是实现我目标的 efficient/best 方法。

我有一个承诺,它会进行 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] 
        } 
} 
]

感谢任何建议。

假设 wsConn 是一个 https://github.com/websockets/ws websocket - 那么你使用的代码只会 "detect" 立即出错 - 任何套接字写入失败都不会被捕获

您还将在任何 wsConn.send 完成之前输出 "INFO: Message broadcast finished" - 因为它是异步的

幸运的是 .send 有一个回调,一旦发送 完成 出错或成功时回调 - 这解决了两个问题

使用 promises 是个好主意,除了最初的 SQL 执行之外你没有使用 promises ,这就是你最终陷入嵌套地狱的原因

我相当有信心(没有你的完整代码我不能确定)下面的代码不仅运行,而且嵌套少得多

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