服务器自动关闭并面临“ERR_STREAM_WRITE_AFTER_END”错误以及每次向客户端发送的数据

Posted

技术标签:

【中文标题】服务器自动关闭并面临“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 【发布时间】:2021-02-09 16:55:01 【问题描述】:

我正在尝试使用数据库 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 到 DB,则会出现以下错误:

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() 问题?以及如何摆脱上述错误?您能否仅在数据发生更改时才将数据从服务器发送到客户端,如果没有更改,则不应通知客户端?如何管理连接并在不使用时关闭它们?有人可以帮我解决上述所有问题吗?谢谢!

【问题讨论】:

【参考方案1】:

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

通常,您会希望无限期地保持事件流打开,除非您有理由关闭它。如果浏览器选项卡关闭、连接丢失等,客户端将自行断开连接。

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

【讨论】:

非常感谢您帮助我,先生...我也尝试从那里删除 response.end() ,然后也收到了该错误。停止发送事件。 events.js:292 抛出错误; // 未处理的 'error' 事件 错误 [ERR_STREAM_WRITE_AFTER_END]: write after end at write_ (_http_outgoing.js:629:17) 你能帮忙吗?非常感谢 @BlessyJulie 试试 NPM 包express-sse...你会发现它使用起来更简单。 先生,很抱歉ping了很多:(我无法理解express-sse,所以我刚刚删除了request.on('close', () =&gt; increment = increment - 1; closeConnection(response); );,现在它不再给出那个错误了。所以想问什么时候标签未使用或标签关闭时连接会自动关闭还是我们需要手动关闭?还有一个请求,先生,您能否指导如何仅在数据更改而不是发送时编写响应每个连接总是如此?你能告诉我如何使用 express-sse 吗?非常感谢,先生!

以上是关于服务器自动关闭并面临“ERR_STREAM_WRITE_AFTER_END”错误以及每次向客户端发送的数据的主要内容,如果未能解决你的问题,请参考以下文章

使用PowerShell关闭Windows更新服务和自动更新Windows 10

Emacs 补全:自动补全还是公司? [关闭]

启动tomcat 后 报出如下错误,并自动关闭了tomcat,请高手解答!

Apache2 - 如何完全关闭端口 80 并强制浏览器自动使用 HTTPS?

比特币交易所面临倒闭,点对点场外交易将盛行

面临问题让用户选择取消静音自动播放 vimeo iframe 嵌入