【问题标题】:Server Sent Event not working:: Error:: net::ERR_INCOMPLETE_CHUNKED_ENCODING 200服务器发送事件不起作用:: 错误:: net::ERR_INCOMPLETE_CHUNKED_ENCODING 200
【发布时间】:2020-06-23 16:02:29
【问题描述】:

我一直在尝试使用以下代码启动和运行基本的服务器发送事件(nodejs+express 用于后端,React 用于前端),但是当我尝试通过终端更新 count 时,onmessage 没有触发.

流程如下:

  1. 让服务器启动并运行。
  2. 打开浏览器并点击localhost:9000
  3. 在 UI 中,我可以看到通知计数为 0
  4. 尝试通过 cURL 在终端中使用POST 调用更新通知计数,如下所示:

curl -X POST -H "Content-Type: application/json" -d '{"count": 10}' -s http://localhost:9000/notification

  1. 在运行服务器的终端外壳中,我可以看到触发了/events 回调,但是count 仍然是0

这是我尝试过的代码。出现主题中提到的错误(在浏览器的控制台中看到)并且 UI 不会随着更新的通知计数而更新。请让我知道我做错了什么:

服务器代码(NodeJS+Express):

const sseHandler = (req: express.Request, res: express.Response) => {
console.log("server sent event handler triggered");
//Mandatory headers and http status to keep connection open
const headers = {
  'Content-Type': 'text/event-stream',
  'Connection': 'keep-alive',
  'Cache-Control': 'no-cache'
};

res.writeHead(200, headers);
//After client opens connection send all notifications as string
const data = `count:${notificationCount}\n\n`;
console.log(data);
res.write(data);
// Generate an id based on timestamp and save res
// object of client connection on clients list
// Later we'll iterate it and send updates to each client
// In Real world scenario, client list should be saved to the DB
const clientId = Date.now();
const newClient = {
  id: clientId,
  res,
};
clients.push(newClient);
// When client closes connection we update the clients list
// avoiding the disconnected one
req.on('close', () => {
  console.log(`${clientId} Connection closed`);
  clients = clients.filter(c => c.id !== clientId);
 });
};

// Iterate clients list and use write res object method to send latest notification count
const sendEventsToAll = (count:number) => {
  console.log("send event to all");
  clients.forEach(c => c.res.write(`count:${count}\n\n`));
};

// Middleware for POST /notification endpoint
const updateNotification = async (
  req: express.Request,
  res: express.Response,
) => {
  let currentCount= req.body.count;
  console.log("post count is: ", currentCount);
  // Send recently updated notification count as POST result
  res.json({count: currentCount});
  // Invoke iterate and send function
  return sendEventsToAll(currentCount);
}

反应代码

const Nav = () => {
const router = useRouter();
const [ notificationCount, setNotificationCount ] = useState(0);

useEffect(() => {
  console.log("rendered on client");
  const events = new EventSource('http://localhost:9000/events');
  events.onmessage = (event) => {
    console.log("Entering on message callback");
    console.log(event);
    // console.log(event.data);
    // const parsedData = JSON.parse(event.data);
    // setNotificationCount(() => parsedData.count);
  };
}, [notificationCount]);

// record rendering counter
metrics.recordCounter({
  name: "NavBar",
  eventName: "render",
  value: 1,
});

return (
  <nav>
    <ul>
      <li className={router.pathname === "/" ? "active" : ""}>
        <Link href="/">
          <a>Home</a>
        </Link>
      </li>
      <li className={router.pathname === "/dangerously_set" ? "active" : ""}>
        <Link href="/xss-testing">
          <a>XSS Testing</a>
        </Link>
      </li>
      {links.map(({ key, href, label }) => (
        <li key={key}>
          <a href={href}>{label}</a>
        </li>
      ))}
      <a href="#" className="notification">
        <span>Notification</span>
        <span className="badge">{notificationCount}</span>
      </a>
    </ul>
  );
 }

【问题讨论】:

    标签: node.js reactjs express next.js eventsource


    【解决方案1】:

    我不得不停止响应主体的默认压缩,这可以解决问题。这是我放置的检查(Content-Type 上的响应标头检查):

    const shouldCompress = (
      req: express.Request,
      res: express.Response
    ): boolean => {
    // don't compress responses explicitly asking not
    if (req.headers["x-no-compression"] || res.getHeader('Content-Type') === 'text/event-stream') {
      return false;
    }
    
    // use compression filter function
      return compression.filter(req, res);
    };
    

    我的 nodejs+express 代码使用如下压缩中间件:

    import compression from "compression";
    ...
    ..
    .
    .
    .
    /**
     * Express application setup
    */
    const expressApp = express();
    
    // setup compression in express
    expressApp.use(compression({ filter: shouldCompress }));
    

    此外,来自服务器的响应应包含以下字段:https://javascript.info/server-sent-events#server-response-format

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-08
      • 2022-01-16
      • 2020-11-04
      • 2018-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-24
      相关资源
      最近更新 更多