nodejs + mysql +个人用户

时间:2015-05-16 10:28:33

标签: node.js

我正在尝试构建一个客户端,它将id(例如电子邮件)发送到服务器上的nodejs程序。电子邮件实际上是登录用户。

nodejs程序应该继续使用该电子邮件地址的相关数据更新客户端上的特定div(比如每隔3秒推送一次数据)。

同样应该在多台机器上完成,其中每台机器都有单独的人员通过电子邮件登录。像gmail上发生的事情。

我已按如下方式构建它,但是当我从多个客户端打开它时,最新客户端(电子邮件)的值会覆盖以前的客户端值和所有客户端显示数据,仅用于最新的电子邮件。

服务器和客户端的代码如下所示。

server.js

var app = require('http').createServer(handler),
    io = require('socket.io').listen(app),
    fs = require('fs'),
    mysql = require('mysql'),
    connectionsArray = [],
    profile_id,
    last_count = 0, //this variable is to check previous count value
    connection = mysql.createConnection({
        host: 'localhost',
        user: 'root',
        password: '', //put your own mysql pwd
        database: 'test', //put your database name
        port: 3306
    }),
    POLLING_INTERVAL = 1000,
    pollingTimer;

// If there is an error connecting to the database
connection.connect(function(err) {
    // connected! (unless `err` is set)
    console.log(err);
});
console.log('DB connected');
// creating the server ( localhost:8000 )
app.listen(8000);

// on server started we can load our client.html page
function handler(req, res) {
    fs.readFile(__dirname + '/indexnew.html', function(err, data) {
        if (err) {
            console.log(err);
            res.writeHead(500);
            return res.end('Error loading client.html');
        }
        console.log('File loaded');
        res.writeHead(200);
        res.end(data);
    });
}

/*
 * HERE IT IS THE COOL PART
 * This function loops on itself since there are sockets connected 
 * to the page. Upon Update it only emits the notification if 
 * the value has changed.
 * Polling the database after a constant interval
 */

var pollingLoop = function() {
    sql = "SELECT count(*) as c FROM activity_log WHERE notified=0 and (profile_id = '" + profile_id + "')";
    console.log(sql);
    // Doing the database query
    var query = connection.query(sql),
        users = []; // this array will contain the result of our db query

    // setting the query listeners
    query
        .on('error', function(err) {
            // Handle error, and 'end' event will be emitted after this as well
            console.log(err);
            updateSockets(err);
        })
        .on('result', function(count) {
            // it fills our array looping on each user row inside the db
            users.push(count);
            // loop on itself only if there are sockets still connected
            if (connectionsArray.length) {
                pollingTimer = setTimeout(pollingLoop, POLLING_INTERVAL);
                updateSockets({
                    users: users,
                    count: count.c
                });
            }
        })
};

// creating a new websocket to keep the content updated without any AJAX request
io.sockets.on('connection', function(socket) {
    console.log('Connected');
    //This variable is passed via the client at the time of socket //connection, see "io.connect(..." line in client.html
    profile_id = socket.handshake.query.profile_id;
    console.log('Number of connections:' + connectionsArray.length);
    // starting the loop only if at least there is one user connected
    if (!connectionsArray.length) {
        pollingLoop();
    }

    socket.on('disconnect', function() {
        var socketIndex = connectionsArray.indexOf(socket);
        console.log('socket = ' + socketIndex + ' disconnected');
        if (socketIndex >= 0) {
            connectionsArray.splice(socketIndex, 1);
        }
    });

    console.log('A new socket is connected!');
    connectionsArray.push(socket);

});

var updateSockets = function(data) {
    if (last_count != data.count) {
        // adding the time of the last update
        data.time = new Date();
        // sending new data to all the sockets connected
        connectionsArray.forEach(function(tmpSocket) {
            tmpSocket.volatile.emit('notification', data);
        });
    }
    last_count = data.count;
};

indexnew.html

<html>

<head>
    <title>Push notification long polling server streaming on a MySQL db</title>
    <style>
        dd,
        dt {
            float: left;
            margin: 0;
            padding: 5px;
            clear: both;
            display: block;
            width: 100%;
        }

        dt {
            background: #ddd;
        }

        time {
            color: gray;
        }
    </style>
</head>

<body>
    <time></time>
    <div id="container">Loading ...</div>
    <script src="socket.io.js"></script>
    <script src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script>
        var rno = Math.floor((Math.random() * 10) + 1);
        // create a new websocket
        var socket = io.connect('http://localhost:8000/?profile_id=' + rno);
        // on message received we print all the data inside the #container div
        socket.on('notification', function(data) {
            var usersList = "<dl>";
            $.each(data.users, function(index, count) {
                usersList += "<dt>" + count.c + "</dt>\n";
            });

            usersList += "</dl>";
            $('#container').html(usersList);

            $('time').html('Last Update:' + data.time);
            $('sql').html('Last Update:' + data.sql);
        });
    </script>
</body>

</html>

1 个答案:

答案 0 :(得分:0)

您的pollingLoop函数和查询的结构方式只能检索最后一个profile_id。原因如下: profile_id变量是一个全局变量,存在于服务器线程上。到目前为止你编程的方式,似乎你希望你的pollingLoop一次处理所有的套接字,但是在pollingLoop中,你使用全局变量profile_id来从数据库中提取信息。每当新用户连接“已连接”的用户时,事件触发,将profile_id更新为该用户。

  • 以下是您可以为此解决的一些选项: 构造您的查询以拉出所有连接的profile_id, 并构建您的update_sockets只发送每个的count profile_id到适当的套接字。
  • 您可以使用&#34; group by&#34;帮助 与你的计数。您可以为每个运行pollingLoop 连接用户。您可以按原样保留查询。

无论哪种方式,您都必须修复您的profile_id,因为在全局设置中包含单个用户的唯一ID并不合理。如果您确实希望profile_id是基于会话的唯一ID,那么执行随机数会有点危险。我建议使用socket.io为每个套接字公开的socket.id。通过这种方式,您不必担心它是独一无二的,您不必将其传递,并且您不必自己存储它。 socket.id将在connectionsArray中可用,因为它包含所有套接字。因此,在pollingLoop中,您可以遍历ID以构建查询,并且在updateSockets中,您可以将结果配对回需要接收特定于该用户的数据的套接字。

关于连接事件中的评论还有一个注意事项: //仅当至少有一个用户连接时才启动循环 这个评论不准确,我认为应该说: //仅在没有其他用户连接的情况下启动循环

我希望能帮到你!