我有一个简单的后端(nodejs + express),可以将数据密集地发送到房间数和接收数据的前端。但是发现了一个奇怪的问题-一旦我停止后端(前端显示为“已断开连接”事件)并重新启动它(前端显示为“已连接”并“连接到XXX室”),前端就会停止接收数据。它仅在页面重新加载后才生效。
后端代码:
import * as express from "express";
import * as http from 'http';
import * as socketio from "socket.io";
import * as path from 'path';
const PORT = process.env.PORT || 8888;
const app = express();
app.set('port', PORT);
app.get('/txs', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/tx-review.html'));
});
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/index-socketio.html'));
});
const server = http.createServer(app);
const io = socketio(server);
const allRooms: string[] = [];
io.on('connection', listen);
function listen(socket: any) {
setInterval(() => {
for (let i = 0; i < allRooms.length; i++) {
const probabilityForRoom = Math.random();
if (probabilityForRoom < 0.15) return;
const room = allRooms[i];
const txs = [];
for (let i = 0; i < 5; i++) {
txs.push({
currency_pair: "btc_try",
currency_pair_guid: `${Math.random()}`,
current_time: new Date().getTime(),
exchange_guid: `${Math.random()}${Math.random()}`,
transaction_amount: Math.random(),
transaction_exchange_name: "btcturk",
transaction_id: `${Math.random()}-${Math.random()}-${Math.random()}-${Math.random()}`,
transaction_price: "21783.0000000000000000",
transaction_timestamp: new Date().getTime()
});
}
console.log(`Sending ${txs.length} transactions to room ${room}.`);
socket.to(room).emit('transaction', {
room,
transactions: txs
});
}
}, 1000);
socket.on('connectToRoom', (rooms: string[] | string) => {
if (!rooms || !rooms.length) {
socket.emit('onError', 'room name isn\'t found');
return;
}
if (!Array.isArray(rooms)) {
rooms = [rooms];
}
rooms.forEach(room => {
console.log('connecting to room', room);
if (allRooms.indexOf(room) === -1) {
allRooms.push(room);
}
socket.join(room, () => {
console.log('connected to room', room);
socket.emit('connectedToRoom', room);
});
});
});
socket.on('disconnect', () => {
console.log('disconnect');
});
}
server.listen(PORT, function () {
console.log(`Server started on port ${PORT} :)`);
});
对应的前端部分:
<script type="text/javascript">
let prevPackTimestamp = new Date().getTime();
let paused = false;
const WS_URL = 'http://localhost:8888';
function clearTable(button) {
const tbody = document.querySelector('#transactions tbody');
tbody.innerHTML = '';
}
function pauseTransactionHandling(button) {
paused = !paused;
button.innerText = paused ? 'Resume' : 'Pause';
}
function subscribe(socket) {
const rooms =[
'all_transactions_btc_usdt',
'all_transactions_btc_jpy',
'all_transactions_btc_gbp',
'all_transactions_btc_eur',
'all_transactions_btc_usd',
'all_transactions_btc_krw',
'all_transactions_btc_aud',
'all_transactions_btc_try',
'all_transactions_btc_thb',
'all_transactions_btc_rub',
'all_transactions_btc_pln',
'all_transactions_btc_idr',
'all_transactions_btc_sgd',
'all_transactions_btc_cad',
'all_transactions_btc_chf',
'all_transactions_btc_zar',
'all_transactions_btc_ngn',
'all_transactions_btc_myr',
'all_transactions_btc_brl',
'all_transactions_btc_php',
'all_transactions_btc_hkd',
'all_transactions_btc_cny',
'all_transactions_btc_inr'
];
rooms.forEach(room => {
socket.emit('connectToRoom', room);
});
}
function htmlToElement(html) {
var template = document.createElement('template');
html = html.trim(); // Never return a text node of whitespace as the result
template.innerHTML = html;
return template.content.children;
}
function addTransaction(transactions) {
if (paused) return;
const source = document.getElementById("rows").innerHTML;
let template = Handlebars.compile(source);
const tbody = document.querySelector('#transactions tbody');
let time = new Date().getTime();
template = template({ transactions, timespan: (time - prevPackTimestamp) / 1000 });
prevPackTimestamp = time;
let elements = htmlToElement(template);
for(let i = 0; i < elements.length; i++) {
tbody.appendChild(elements[i]);
}
}
function connectSocketListeners(socket) {
console.log('SOCKET: connect');
subscribe(socket);
socket.on('transaction', data => {
addTransaction(data.transactions);
});
socket.on('connectedToRoom', room => {
console.log('SOCKET: connected to room', room, new Date().toISOString());
});
socket.on('onError', data => {
console.log('SOCKET: error', data, new Date().toISOString());
});
socket.on('disconnect', function() {
console.log('SOCKET: disconnect', new Date().toISOString());
});
}
document.addEventListener('DOMContentLoaded', function() {
var socket = io(WS_URL, { forceNew: true });
socket.once('connect', () => connectSocketListeners(socket));
});
</script>
UPD :This question对我没有帮助,因为我看到所有订阅都已刷新。