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

时间:2018-09-29 11:37:19

标签: javascript loops error-handling promise continue

我非常怀疑我编写的代码是实现目标的有效/最佳方式。

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

感谢任何建议。

1 个答案:

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