【问题标题】:Socket.io and Node.js with mysql not returning results as expeted带有 mysql 的 Socket.io 和 Node.js 未按预期返回结果
【发布时间】:2017-01-15 06:08:01
【问题描述】:

编辑:我重新表述我的问题:Socket.io 不等待回调并且连接从未被接受。请参阅下面的编辑 2/尝试 1

这是根据数据库检查身份验证令牌。有人能发现这里有什么问题吗?

var checkauth = function(auth) {
    var rs = 0;
    var sql = 'SELECT * FROM clients WHERE pword=\''+auth+'\''; 
    // Copied from debug session and got results: SELECT * FROM clients WHERE pword='d98e623c7a74a178703d17e1fd536b1488724acd41e71f178331c768c385bda2c82d2bcb60cbb4650be375ad4734c63fb694bd164c138f9abe0c51f37f9a7e33'
    var query = connection.query(sql);
    query
        .on('error', function(err) {
            console.log( err );
        })
        .on('result', function( row ) {
            rs = Number(row.client_id); // This never fires!!?!?!
        })
        .on('end',function(){

        });
    if (rs == 0) {
        sql = 'SELECT * FROM users WHERE pword=\''+auth+'\'';
        query = connection.query(sql);
        query
            .on('error', function(err) {
                console.log( err );
            })
            .on('result', function( row ) {
                rs = Number(row.client_id); // This never fires!!?!?!
            })
            .on('end',function(){
            });
    }
    return rs;
}

编辑 1:我使用以下循环来验证运行该函数的 socket.io 连接,好的,所以我知道我必须等待数据库完成,我将回调放在哪里?

io.use(function(socket, next){
    console.log("Query: ", socket.handshake.query);
    // return the result of next() to accept the connection.
    socket.clientid = 0;
    socket.clientid = checkauth(socket.handshake.query.auth);
    console.log("CID:"+socket.clientid);
    if (socket.clientid != 0) {
        return next();
    }
    // call next() with an Error if you need to reject the connection.
    next(new Error('Authentication error'));
});

根据 Johannes 的建议编辑 2/尝试 1:

var checkauth = function(auth, cb) {
    var rs = 0;
    var sql = 'SELECT * FROM clients WHERE pword=?';
    var query = connection.query(sql, [auth]);
    query
        .on('error', function(err) {
            console.log(err);
        })
        .on('result', function(row) {
            rs = Number(row.client_id);
        })
        .on('end', function() {
            if (rs == 0) {
                sql = 'SELECT * FROM users WHERE pword=?';
                query = connection.query(sql, [auth]);
                query
                    .on('error', function(err) {
                        console.log(err);
                    })
                    .on('result', function(row) {
                        rs = Number(row.client_id);
                    })
                    .on('end', function() {
                        cb(rs);
                    });
            }
        });
}

io.use(function(socket, next){
    console.log("Query: ", socket.handshake.query);
    // return the result of next() to accept the connection.
    socket.clientid = 0;
    var auth = socket.handshake.query.auth;

    checkauth(auth, function(clientid){
        socket.clientid = clientid;
        if (clientid != 0) {
            return next();
        }
        console.log('CLIENID', clientid);
        next(new Error('Authentication error'));
    });

    // if (socket.clientid != 0) {
    //     return next();
    // }
    // // call next() with an Error if you need to reject the connection.
    // next(new Error('Authentication error'));
});

【问题讨论】:

  • 您是否记录了任何错误?
  • 什么都没有,没有错误,调试器只是遍历查询,不会遇到错误、结果或结束
  • return rs 应该在回调中,否则它会一直返回 rs == 0
  • 这都是异步的,所以你必须等到数据库调用完成
  • @shikhar 你的意思是像:query.on('result',func(row) { rs = row.clinet_id; return rs; });尝试过但现在返回 undefined

标签: mysql node.js socket.io


【解决方案1】:

整个过程是异步的。你必须做两件事:

将所有内容移动到事件回调中并 向您的 checkAuth 函数添加回调或承诺。您还应该转义插入的数据。

编辑解决方案

var checkauth = function(auth, cb) {
    var rs = 0;
    var sql = 'SELECT * FROM clients WHERE pword=?';
    var query = connection.query(sql, [auth], (err, client) => {
        if(err || !client || client.length < 1) return cb(err || new Error('unkown client')); 
        sql = 'SELECT * FROM users WHERE pword=?';
        query = connection.query(sql, [auth], (err, user) => {
            if(err || !user || user.length < 1) return cb(err || new Error('unkown user'));
            cb(null, client[0].client_id);
        });
    });
}

注意:为什么要首先进行 2 次查询并为用户的每个客户端存储密码?

原始答案:

var checkauth = function(auth, cb) {
    var rs = 0;
    var sql = 'SELECT * FROM clients WHERE pword=?';
    var query = connection.query(sql, [auth]);
    query
        .on('error', function(err) {
            console.log(err);
        })
        .on('result', function(row) {
            rs = Number(row.client_id); // This never fires!!?!?!
        })
        .on('end', function() {
            if (rs == 0) {
                sql = 'SELECT * FROM users WHERE pword=?';
                query = connection.query(sql, [auth]);
                query
                    .on('error', function(err) {
                        console.log(err);
                    })
                    .on('result', function(row) {
                        rs = Number(row.client_id); // This never fires!!?!?!
                    })
                    .on('end', function() {
                        cb(rs);
                    });
            }
        });
}

checkauth(123, function(clientId){
    console.log('CLIENID', clientId);
});

【讨论】:

  • 嗨 Johannes,感谢您的建议,但我认为这与 io.use 不等待检查完成有关,请参阅我的编辑/尝试1
  • @johan 这是不可能的,因为 cb 会以这种方式被调用两次。不过,您可以简化整个事情。
  • 哦,是的,这个答案更短更好!我必须检查两个表的原因是因为它是这样设置的,我必须从现有的后端开发前端。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多