服务器自动关闭并面临 'ERR_STREAM_WRITE_AFTER_END' 错误以及每次向客户端发送数据
Server automatically getting closed and facing 'ERR_STREAM_WRITE_AFTER_END' error along with data sending every time to client
我正在尝试使用数据库中的服务器发送事件获取实时数据 Mysql 并将值发送到客户端 Reactjs。这是代码:
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 ,
})
});
使用它我能够获取数据,但几秒钟后连接关闭,然后如果数据正在 POST 到数据库,则会出现错误:
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'
}
不明白我错过了什么,连接自动关闭。如何克服自动连接 end() 问题?以及如何摆脱上述错误?你能帮我把数据从服务器发送到客户端只有当数据发生变化时,如果没有变化那么客户端不应该被通知吗?如何管理连接并在不使用时关闭它们?有人可以帮我解决上述所有问题吗?谢谢!
在您的代码中,您正在调用 response.end()
,这将断开事件流。
通常情况下,您会希望事件流无限期地保持打开状态,除非您有理由将其关闭。如果浏览器选项卡关闭、连接丢失等,客户端将自行断开连接。
此外,您可以考虑使用现有模块,例如 express-sse:https://www.npmjs.com/package/express-sse 这可以节省您实施协议的时间。
我正在尝试使用数据库中的服务器发送事件获取实时数据 Mysql 并将值发送到客户端 Reactjs。这是代码:
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 ,
})
});
使用它我能够获取数据,但几秒钟后连接关闭,然后如果数据正在 POST 到数据库,则会出现错误:
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'
}
不明白我错过了什么,连接自动关闭。如何克服自动连接 end() 问题?以及如何摆脱上述错误?你能帮我把数据从服务器发送到客户端只有当数据发生变化时,如果没有变化那么客户端不应该被通知吗?如何管理连接并在不使用时关闭它们?有人可以帮我解决上述所有问题吗?谢谢!
在您的代码中,您正在调用 response.end()
,这将断开事件流。
通常情况下,您会希望事件流无限期地保持打开状态,除非您有理由将其关闭。如果浏览器选项卡关闭、连接丢失等,客户端将自行断开连接。
此外,您可以考虑使用现有模块,例如 express-sse:https://www.npmjs.com/package/express-sse 这可以节省您实施协议的时间。