服务器自动关闭并面临“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

查看:81
本文介绍了服务器自动关闭并面临“ERR_STREAM_WRITE_AFTER_END"错误以及每次向客户端发送数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用来自数据库 Mysql 的服务器发送事件获取实时数据并将值发送到客户端 Reactjs.代码如下:

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 ,
     })
});

使用它我能够获取数据,但几秒钟后连接被关闭,然后如果数据被 POST 到 DB 那么这会给出一个错误:

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'
}

不明白我错过了什么,连接自动关闭.如何克服自动连接 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!

推荐答案

在您的代码中,您正在调用 response.end(),这将断开事件流.

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.

此外,您可以考虑使用像 express-sse 这样的现有模块:https://www.npmjs.com/package/express-sse 这可以为您节省一些时间来实现协议.

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.

这篇关于服务器自动关闭并面临“ERR_STREAM_WRITE_AFTER_END"错误以及每次向客户端发送数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆