我的前端坑
  • 关于本书
  • CSS JS 常用
    • 常用 CSS 样式
    • 坑爹的 CSS
    • sass 入门
    • canvas 总结
    • 常用 JS 函数
    • 表单和 FormData 对象
    • 水平滑动 tab 居中
    • js 中的 this
    • sse 和 fetch
    • js 原型链与 class 类
  • TypeScript
    • TS 概念
    • interface 与 type
    • interface 接口
    • Ts 配合 ESLint 和 prettier
  • 小程序
    • 常用小程序代码
  • VUE
    • VUE2 小技巧
    • VUE-CLI 中的 NODE_ENV
  • VUE3
    • VUE3 自行构建 sfc 遇到的坑
    • VUE3 v-model 的实现
    • VUE3 使用总结
    • VUE3 ref
  • vite
    • vite
  • http 请求
    • 前端实现下载
    • cors 跨域请求
    • windows hosts 文件
    • err_blocked_by_client 错误
  • 前端工具
    • npm 和 Node
      • 常见问题
      • npmTips
      • package.json 与 package-lock.json
      • npx
      • exports 与 module.exports
      • ESLint
    • VIM
      • vim 常用
    • Git
      • Git 常用命令
      • Git 小 tips
    • express
  • 后端工具
    • mysql 常见问题
    • docker 常见问题
    • docker
  • java
    • java 常用
    • lambda 表达式
    • java 字符串
    • java 泛型
    • java 反射
    • intellij IDEA
    • 多态
    • java 包管理
    • sql 查询语言
    • java 反射
    • java 异常
    • java 集合
    • spring
  • 命令行
    • 命令行 常用
  • 专利撰写 ppt
  • 后台简述
Powered by GitBook
On this page

Was this helpful?

  1. CSS JS 常用

sse 和 fetch

Previousjs 中的 thisNextjs 原型链与 class 类

Last updated 1 year ago

Was this helpful?

服务器向浏览器推送信息,除了 WebSocket,还有一种方法:Server-Sent Events(SSE)。 严格地说,HTTP 协议无法做到服务器主动推送信息。 但是,有一种变通方法,就是服务器向客户端声明,接下来要发送的是流信息(streaming)。

也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来。这时,客户端不会关闭连接,会一直等着服务器发过 来的新的数据流,视频播放就是这样的例子。本质上,这种通信就是以流信息的方式,完成一次用时很长的下载。

SSE 就是利用这种机制,使用流信息向浏览器推送信息。它基于 HTTP 协议。 SSE 是单向通道,只能服务器向浏览器发送,因为流信息本质上就是下载。

SSE 和 webSocket 的区别

  • SSE 使用 HTTP 协议,现有的服务器软件都支持。WebSocket 是一个独立协议。

  • SSE 属于轻量级,使用简单;WebSocket 协议相对复杂。

  • SSE 默认支持断线重连,WebSocket 需要自己实现。

  • SSE 一般只用来传送文本,二进制数据需要编码后传送,WebSocket 默认支持传送二进制数据。

  • SSE 支持自定义发送的消息类型。

SSE 的客户端 API 部署在 EventSource 对象上。具体教程可 看 。

这里我们使用 fetch api 处理 Content-Type 为 text/event-stream 的流数据

定义类:

// requestFetch.ts

export class FetchAiStream {
  controllerAbort: AbortController;
  constructor() {
    this.controllerAbort = new AbortController();
  }
  fetchStream(url: string, params: any) {
    const { onmessage, onabort, onclose, headers, ...otherParams } = params;
    // 错误处理程序
    const errorHandler = (err: any) => {
      if (err.message.includes("aborted")) {
        onabort(err);
      } else {
        console.log(`错误信息:${err.message ?? "未知错误"}`);
      }
    };
    const push = async (controller: any, reader: ReadableStreamDefaultReader) => {
      try {
        const { value, done } = await reader.read();
        if (done) {
          controller.close();
          onclose?.();
        } else {
          onmessage?.(new TextDecoder().decode(value));
          controller.enqueue(value);
          push(controller, reader);
        }
      } catch (err: any) {
        // controller.console;
        errorHandler(err);
      }
    };
    // 发送请求
    return fetch(url, {
      signal: this.controllerAbort.signal,
      headers: { "Content-Type": "application/json", ...headers },
      ...otherParams,
    })
      .then((response: Response) => {
        // 以ReadableStream解析数据
        const reader = response.body?.getReader();
        const stream = new ReadableStream({
          start(controller) {
            push(controller, reader);
          },
        });
        return stream;
      })
      .then((stream) => new Response(stream, { headers: { "Content-Type": "text/html" } }).text())
      .catch((err: Error) => {
        errorHandler(err);
      });
  }
  abort() {
    this.controllerAbort.abort();
  }
}

使用:

import { FetchAiStream } from "./requestFetch";
// 构造自定义fetch请求的实例
let fetchAiAnswer: FetchAiStream;
fetchAiAnswer = new FetchAiStream();

fetchAiAnswer.fetchStream("https://chatgpt.cmm/xxx/xx/x", {
  method: "post",
  body: JSON.stringify({
    message: "帮我随机生成一个表格",
  }),
  headers: {
    accept: "text/event-stream",
  },
  // 处理获取的数据流
  onmessage: (res: any) => {
    console.log(JSON.stringify(res));
  },
  // 中断请求
  onabort: (res: any) => {
    console.log("中断请求成功");
  },
  // 请求完成
  onclose: (res: any) => {
    console.log("请求完成");
  },
});
Server-Sent Events 教程