为什么客户端在node + express + socket.io + jade简单app中断开连接并重新连接

时间:2013-09-22 18:38:11

标签: javascript node.js express socket.io pug

我创建了一个简单的应用程序,尝试集成node,express,socket.io和jade。用户在文本字段中输入一些字符串(“工具ID”)并单击提交按钮。该文本只是转换为全部大写,结果将附加到页面上的结果部分。对于查看该页面的其他客户,应自动更新结果。

它主要起作用。但问题是,在用户单击页面上的提交按钮以提交工具ID之后,节点控制台和浏览器javascript控制台都会显示客户端断开连接然后重新连接。

对于用户来说,看起来结果会在几分之一秒内正确更新。然后结果变成空白,持续一秒钟。然后重新显示结果。由于我用结果显示用户的会话ID,我可以看到会话ID在短时间内发生变化,而结果变为空白。

请注意,如果不同的客户端只是查看页面,而不是以其他方式进行交互,则结果会平滑更新(没有短暂的结果空白时间),并且客户端似乎根本没有断开连接。

我不希望客户端在单击表单上的“提交”按钮时断开连接并重新连接。有人能告诉我为什么会这样,以及我应该如何正确地做到这一点?

我的 app.js (服务器)

var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
io = require('socket.io').listen(server); // without the var, this becomes available to other files like routes.
var path = require('path');
var routes = require('./routes/routes');
var process = require('./routes/process');
var _ = require("underscore");

// all environments
app.set('port', 3097);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
//app.use(express.logger('dev'));
app.use(express.bodyParser()); //Tells server to support JSON, urlencoded, and multipart requests
app.use(express.methodOverride());
app.use(express.cookieParser('i7iir5b76ir857bveklfgf'));
app.use(express.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

var toolIDs = [];

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

io.on("connection", function(socket) {
    console.log("Client connected.  Sending Update");

    socket.on("toolsRequest", function() {
        socket.emit('toolsReady', {toolIDs: toolIDs}); //This should go to the client that just connected.
    });

    socket.on("disconnect", function() {
        console.log("Client Disconnected");
    });

    socket.on("toolsUpdate", function(data) {
        processedToolID = process.process(data.toolID);
        toolIDs.push({id: data.id, inputToolID: data.toolID, outputToolID: processedToolID}); 
        io.sockets.emit("toolsUpdated", {toolIDs: toolIDs}); //This should go to all clients
        console.log('Results Updated - notifying all clients');
    });
});

// display main page
app.get('/', routes.home);

server.listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

我的 routes.js

/*
 * GET home page.
 */

exports.home = function(req, res){
    res.render('home', { title: 'Tool'});
    console.log("Just called route.home");
};

我的 home.jade

doctype 5
html
    head
        title= title
        link(rel='stylesheet', href='/bootstrap/css/bootstrap.min.css')
        link(rel='stylesheet', href='/bootstrap/css/bootstrap-responsive.min.css')
        script(src='/socket.io/socket.io.js')
        script(src="http://code.jquery.com/jquery.min.js")
        script(src='/js/index.js')
block content
    #wrapper
    h1 
        a(href='/') TOOL
    #display
        div.row-fluid
            div.inlineBlock
                form#toolForm
                    label Tool ID
                    input(type="text", placeholder="e.g. abc123")#toolID
                    span.help-block You may enter a string.
                    button(class="btn")#submit
                        | Submit
                br
            div.inlineBlock.topAligned
                h2 Results
                br
                div#results
                br

我的 index.js (客户端)

function init() {

    /* 
    On client init, try to connect to the socket.IO server.
    */
    var socket = io.connect('http://example.com:3097/');

    //We'll save our session ID in a variable for later
    var sessionID = '';

    //Helper function to update the results  
    function updateResults(toolIDs) {
        $('#results').html('');
        for (var i = 0; i < toolIDs.length; i++) {
            $('#results').append('<span id="' + toolIDs[i].id + '">' + '<b>Creator ID:</b> ' + toolIDs[i].id + ' <b>Your ID:</b> ' + sessionID + ' <b>Input Tool:</b> ' + toolIDs[i].inputToolID + ' <b>Output Tool:</b> ' + toolIDs[i].outputToolID + (toolIDs[i].id === sessionID ? '<b>(You)</b>' : '') + '<br /></span>');
        } 
    }

    /*
    When the client successfully connects to the server, an
    event "connect" is emitted.
    */
    socket.on('connect', function () {
        sessionID = socket.socket.sessionid;
        // Note this appears in the browser Javascript console, not node console
        console.log('You are connected as: ' + sessionID);    
        socket.emit('toolsRequest'); //Request the tools data so we can update results
    });

    socket.on('toolsReady', function(data) {
        updateResults(data.toolIDs);
        console.log('Results have been updated from socket.on.toolsReady');  
    });

    socket.on('toolsUpdated', function (data) {
        updateResults(data.toolIDs);
        console.log('Results updated from socket.on.toolsUpdated');
    });

    /*
    Log an error if unable to connect to server
    */
    socket.on('error', function (reason) {
        console.log('Unable to connect to server', reason);
    });

    function getCitations() {
        var toolID = $('#toolID').val()
        socket.emit('toolsUpdate', {id: sessionID, toolID: toolID});
    }

    $('#submit').on('click', getCitations);
}

$(document).on('ready', init);

当客户点击提交按钮时,这是我在节点控制台中看到的内容:

 debug - websocket writing 5:::{"name":"toolsUpdated","args":[{"toolIDs":[{"id":"5a1dfX2dmxcogYT_11e8","inputToolID":"a123123","outputToolID":"A123123"},{"id":"OIuqao6TsTeddQm111e-","inputToolID":"1abcdefg","outputToolID":"1ABCDEFG"},{"id":"Qr_YQ2ZhQHbDpBlk11e_","inputToolID":"abcdefg","outputToolID":"ABCDEFG"}]}]}
Results Updated - notifying all clients
Just called route.home
   info  - transport end (socket end)
   debug - set close timeout for client Qr_YQ2ZhQHbDpBlk11e_
   debug - cleared close timeout for client Qr_YQ2ZhQHbDpBlk11e_
   debug - cleared heartbeat interval for client Qr_YQ2ZhQHbDpBlk11e_
Client Disconnected
   debug - discarding transport
   debug - served static content /socket.io.js
   debug - client authorized
   info  - handshake authorized 2bPKGgmLdD4fp-vz11fA
   debug - setting request GET /socket.io/1/websocket/2bPKGgmLdD4fp-vz11fA
   debug - set heartbeat interval for client 2bPKGgmLdD4fp-vz11fA
   debug - client authorized for
   debug - websocket writing 1::
Client connected.  Sending Update
   debug - websocket writing 5:::{"name":"toolsReady","args":[{"toolIDs":[{"id":"5a1dfX2dmxcogYT_11e8","inputToolID":"a123123","outputToolID":"A123123"},{"id":"OIuqao6TsTeddQm111e-","inputToolID":"1abcdefg","outputToolID":"1ABCDEFG"},{"id":"Qr_YQ2ZhQHbDpBlk11e_","inputToolID":"abcdefg","outputToolID":"ABCDEFG"}]}]}

谢谢,感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您的提交按钮实际上正在重新加载页面,这就是套接字断开连接的原因,以及为什么您在短时间内看到套接字响应。只是阻止提交按钮的默认操作。改变这个:

$('#submit').on('click', getCitations);

类似的东西:

$('#submit').click(function(event) {
  event.preventDefault();
  getCitations();
});