服务器自动关闭并面临 '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 这可以节省您实施协议的时间。