gpt4 book ai didi

node.js - 在 ReactJs 中使用 EventSource 消费事件流时获取 net::ERR_INCOMPLETE_CHUNKED_ENCODING 200

转载 作者:行者123 更新时间:2023-12-03 14:06:12 24 4
gpt4 key购买 nike

我有一个非常简单的 Node 服务,公开了一个旨在使用服务器发送事件(SSE)连接的端点,以及一个非常基本的 ReactJs 客户端,通过 EventSource.onmessage 使用它。

首先,当我在 updateAmountState (Chrome Dev) 中设置调试点时,我看不到它被唤起。

其次,我收到 net::ERR_INCOMPLETE_CHUNKED_ENCODING 200(正常)。根据https://github.com/aspnet/KestrelHttpServer/issues/1858 “chrome 中的 ERR_INCOMPLETE_CHUNKED_ENCODING 通常意味着在写入响应正文的过程中应用程序抛出了未捕获的异常”。然后我检查了服务器端是否发现任何错误。好吧,我在 setTimeout(() => {... 中的 server.js 中的几个地方设置了断点,并且我看到它定期运行。我希望每行只运行一次。所以看来前端是尝试永久调用后端并收到一些错误。

整个应用程序,无论是 ReactJs 中的前端还是 NodeJs 中的服务器,都可以在 https://github.com/jimisdrpc/hello-pocker-coins 中找到。 .

后端:

const http = require("http");

http
.createServer((request, response) => {
console.log("Requested url: " + request.url);

if (request.url.toLowerCase() === "/coins") {
response.writeHead(200, {
Connection: "keep-alive",
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache"
});

setTimeout(() => {
response.write('data: {"player": "Player1", "amount": "90"}');
response.write("\n\n");
}, 3000);

setTimeout(() => {
response.write('data: {"player": "Player2", "amount": "95"}');
response.write("\n\n");
}, 6000);
} else {
response.writeHead(404);
response.end();
}
})
.listen(5000, () => {
console.log("Server running at http://127.0.0.1:5000/");
});

前端:

import React, { Component } from "react";
import ReactTable from "react-table";
import "react-table/react-table.css";
import { getInitialCoinsData } from "./DataProvider";

class App extends Component {
constructor(props) {
super(props);
this.state = {
data: getInitialCoinsData()
};

this.columns = [
{
Header: "Player",
accessor: "player"
},
{
Header: "Amount",
accessor: "amount"
}
];
this.eventSource = new EventSource("coins");
}


componentDidMount() {
this.eventSource.onmessage = e =>
this.updateAmountState(JSON.parse(e.data));
}

updateAmountState(amountState) {
let newData = this.state.data.map(item => {
if (item.amount === amountState.amount) {
item.state = amountState.state;
}
return item;
});

this.setState(Object.assign({}, { data: newData }));
}

render() {
return (
<div className="App">
<ReactTable data={this.state.data} columns={this.columns} />
</div>
);
}
}

export default App;

我在 chrome 上看到的异常:

enter image description here

所以我的直接问题是:为什么我收到 ERR_INCOMPLETE_CHUNKED_ENCODING 200?我是否缺少后端或前端的某些内容?

一些提示可能对我有帮助:

  1. 为什么我看到 websocket 处于 oending 状态,因为我根本没有使用 websocket?我知道基本的区别(websocket 是双向的,从前到后和从后到前,是一个不同的协议(protocol),而 SSE 通过 http 运行,只是从后到前)。但使用websocket根本不是我的本意。 (参见下面打印屏幕中的蓝线)

  2. 为什么我看到 0 字节和 236 字节的事件源都失败了。我知道 eventsource 正是我在编写“this.eventSource = new EventSource("coins");”时尝试使用的内容。 (请参阅下面打印屏幕中的读取行)

  3. 至少对我来说非常奇怪,有时当我终止服务时我可以看到 updateAmountState 方法被调用。

  4. 如果在浏览器中调用 localhost:5000/coins,我可以看到服务器应答响应(都是 json 字符串)。我可以假设我对服务器进行了正确编码,并且错误仅出现在前端吗?

最佳答案

以下是您问题的答案。

  1. 您看到正在运行的 websocket 与您在此处发布的代码无关。它可能与您在应用程序中使用的另一个 NPM 包有关。您也许可以通过查看网络请求中的 header 来找出它来自哪里。
  2. eventsource 请求失败的最可能原因是它们超时。 Chrome 浏览器将在两分钟不活动后终止不活动的流。如果你想让它保持事件状态,你需要添加一些代码,以至少每两分钟一次从服务器向浏览器发送一些内容。为了安全起见,最好每分钟发送一些内容。下面是您需要的示例。如果您在服务器代码中的第二个 setTimeout 之后添加它,它应该可以满足您的需要。
const intervalId = setInterval(() => {
res.write(`data: keep connection alive\n\n`);
res.flush();
}, 60 * 1000);

req.on('close', () => {
// Make sure to clean up after yourself when the connection is closed
clearInterval(intervalId);
});
  • 我不确定为什么您有时会看到 updateAmountState 方法被调用。如果您没有一致地看到它,这可能不是一个主要问题,但它可能有助于清理 setTimeout,以防服务器在完成之前停止。您可以通过将它们声明为变量,然后将变量名称传递给关闭事件处理程序中的 clearTimeout 来实现此目的,类似于我在上面 #2 的示例中对间隔所做的操作。
  • 您的代码设置正确,您看到的错误是由于 Chrome 浏览器超时造成的。如果您想阻止错误发生,请使用类似于上面答案#2 中的代码。
  • 关于node.js - 在 ReactJs 中使用 EventSource 消费事件流时获取 net::ERR_INCOMPLETE_CHUNKED_ENCODING 200,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56450228/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com