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

我创build了一个简单的应用程序,试图整合node,express,socket.io和jade。 用户在文本字段中input一些string(“工具ID”),然后单击一个提交button。 该文本被简单地转换为全部大写,结果被附加到页面上的结果部分。 结果应该自动更新为查看页面的其他客户端。

它大部分工作。 然而,问题是,用户点击页面上的提交button来提交工具ID后,节点控制台和浏览器的JavaScript控制台都显示客户端断开,然后重新连接。

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

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

当他们点击表单上的提交button时,我不希望客户端断开连接并重新连接。 有人能告诉我为什么发生这种情况,我应该如何正确地做到这一点?

我的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="eg 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); 

这是我在客户端点击提交button时在节点控制台中看到的内容:

  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"}]}]} 

谢谢,我感谢帮助。

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

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

类似的东西:

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