问题
I am trying to get real-time data using Server-Sent Events from the Database Mysql and sending the value to the client Reactjs. Here is the code:
server.js
const mysql = require('mysql');
const app = require('express')()
const fetch = require('node-fetch');
const con = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
database: 'databasetest',
});
var increment = 0;
app.get('/stream/:abc/:qwe', (request, response) => {
console.log(`Request url: ${request.url}`);
var startDate = request.params.abc
var endDate = request.params.qwe
request.on('close', () => {
increment = increment - 1;
closeConnection(response);
});
response.writeHead(200, {
'Connection': 'keep-alive',
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Access-Control-Allow-Origin': '*'
});
setTimeout(() => {
var initial_result;
console.log("The connection number is ", (++increment))
setInterval(() => {
con.query('SELECT * FROM status_table where start_time BETWEEN ? and ?', [startDate, endDate], (err, rows) => {
if (err) {
console.log('error', err.message, err.stack)
}
if (JSON.stringify(rows) === JSON.stringify(initial_result)) {
} else {
if (Changed(initial_result, rows)) {
let data = null;
const url = "http://localhost:8080/data?startTime=" + startDate + "&endTime=" + endDate;
data = getData(url);
data.then(function (result) {
console.log("Data is sent")
response.write("event: executinghello\n");
response.write('data: ' + JSON.stringify(result));
response.write("\n\n");
eventHistory.push(result);
response.end()
})
initial_result = rows;
}
}
})
function Changed(pre, now) {
if (pre != now) {
return true
} else {
return false
}
}
}, 5000);
}, 3000);
});
app.listen(4001, () => console.log('SSE app listening on port 4001!'))
async function getData(url) {
try {
const response = await fetch(url);
const json = await response.json();
return json;
} catch (error) {
console.log(error);
return error;
}
};
function closeConnection(response) {
if (!response.finished) {
response.end();
console.log('Stopped sending events.');
}
}
client.js
this.eventSource = new EventSource("http://localhost:4001/stream/"+startDate+"/"+endDate);
this.eventSource.addEventListener("executinghello", e => {
const data = JSON.parse(e.data);
data.sort((a, b) => parseFloat(b.id) - parseFloat(a.id));
this.setState({
isLoaded: true,
allData: data ,
})
});
Using this I am able to get the data but after some seconds the connection gets closed and then if data is getting POST to DB then this gives an error as:
Data is sent
events.js:292
throw er; // Unhandled 'error' event
^
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at write_ (_http_outgoing.js:629:17)
at ServerResponse.write (_http_outgoing.js:621:15)
at Query.<anonymous> (C:\Users\Documents\socket-io-server\app.js:73:24)
at Query.<anonymous> (C:\Users\Documents\socket-io-server\node_modules\mysql\lib\Connection.js:526:10)
at Query._callback (C:\Users\Documents\socket-io-server\node_modules\mysql\lib\Connection.js:488:16)
at Query.Sequence.end (C:\Users\Documents\socket-io-server\node_modules\mysql\lib\protocol\sequences\Sequence.js:83:24)
at Query._handleFinalResultPacket (C:\Users\Documents\socket-io-server\node_modules\mysql\lib\protocol\sequences\Query.js:149:8)
at Query.EofPacket (C:\Users\Documents\socket-io-server\node_modules\mysql\lib\protocol\sequences\Query.js:133:8)
at Protocol._parsePacket (C:\Users\Documents\socket-io-server\node_modules\mysql\lib\protocol\Protocol.js:291:23)
at Parser._parsePacket (C:\Users\Documents\socket-io-server\node_modules\mysql\lib\protocol\Parser.js:433:10)
Emitted 'error' event on ServerResponse instance at:
at writeAfterEndNT (_http_outgoing.js:684:7)
at processTicksAndRejections (internal/process/task_queues.js:85:21) {
code: 'ERR_STREAM_WRITE_AFTER_END'
}
Not understanding what I have missed and the connections automatically getting closed. How to overcome the automatic connection end() issue? And how to get rid of this above Error? And can you please help me in sending the data from server to client only when there is a change in the data, if no change then the client should not be notified of the same? How to manage connections and close them when not in use? Can someone please help me with all the above queries? Thanks!
回答1:
In your code, you're calling response.end()
, which will disconnected the event stream.
Normally, you would want to keep the event stream open indefinitely, unless you had a reason to close it. The client will disconnect itself if the browser tab is closed, connection is lost, etc.
Also, you might consider using an existing module like express-sse: https://www.npmjs.com/package/express-sse This can save you some time in implementing the protocol.
来源:https://stackoverflow.com/questions/64553979/server-automatically-getting-closed-and-facing-err-stream-write-after-end-erro