前端模拟 流式文本接口 打字机效果 mockStreamText

源码已在文章最后给出

说明书

mockStreamText 这是一个用于在前端 模拟文本流式 展示效果的工具函数,能够将完整文本按指定的片段大小和时间间隔逐步展示,适用于 模拟 AI 对话回复打字机效果 等场景。函数具备完善的参数验证和错误处理机制,确保运行的健壮性。

参数说明

参数名 类型 必选 说明
fullText string 需要进行流式展示的完整文本内容
options object 配置选项对象,包含以下属性

options 配置项

配置项 类型 默认值 说明
chunkSize number 5 每次展示的文本片段大小(正整数)
interval number 50 每次展示的时间间隔(毫秒,正整数)
onChunk function () => {} 每次片段更新时的回调函数,接收当前已展示的文本作为参数
onFinal function () => {} 文本全部展示完成时的回调函数,接收完整文本作为参数
onError function (err) => console.error(...) 发生错误时的回调函数,接收错误对象作为参数

返回值

返回一个取消函数,调用该函数可以终止流式展示过程并释放相关资源。

错误处理

函数会对输入参数进行严格验证,当参数不符合要求时会通过 onError 回调抛出以下错误:

  • fullText 必须是字符串类型:当第一个参数不是字符串时
  • chunkSize 必须是正整数:当 chunkSize 不是正整数时
  • interval 必须是正整数:当 interval 不是正整数时
  • onChunk, onFinal 和 onError 必须是函数:当回调函数不是函数类型时

使用示例

以下仅展示核心的JS食用方法

(利用vue的响应式,displayText内容变化,会自动触发页面渲染,实现打字机效果)

javascript 复制代码
// 引入前端虚拟流式加载工具类
import { mockStreamText } from "@/utils/typeWriter.js"

const backendText = "这是一段需要流式展示的文本内容...";
const displayText = ref("");
const isStreaming = ref(true);

// 启动流式展示
const cancelStream = mockStreamText(backendText, {
    chunkSize: 5,          // 每次展示5个字符
    interval: 50,          // 每50毫秒展示一次
    onChunk: (text) => {   // 片段更新时更新显示
        displayText.value = text;
    },
    onFinal: (fullText) => {  // 展示完成时
        isStreaming.value = false;
        console.log('流式展示结束');
    },
    onError: (err) => {    // 错误处理
        isStreaming.value = false;
        console.error('发生错误:', err.message);
        // 可以在这里添加错误提示UI
    }
});

// 如需中途取消展示
// cancelStream();

特殊情况处理

  • fullText 为空字符串时,会直接触发 onChunk("")onFinal(""),不启动定时器
  • 调用返回的取消函数后,会终止定时器并标记为已取消,避免后续回调执行

工作原理

  1. 进行参数验证,确保输入符合要求
  2. 初始化状态变量(当前位置、定时器、取消标记等)
  3. 定义核心处理函数 process,负责计算片段、触发回调和状态更新
  4. 立即执行一次 process 并设置定时器循环执行
  5. 返回取消函数,用于终止流程并释放资源

该工具函数源码

javascript 复制代码
// 模拟文本流式展示的工具函数(增强健壮性版本)
export function mockStreamText(fullText, options = {}) {
  // 1. 参数验证与默认值处理
  if (typeof fullText !== "string") {
    throw new TypeError("fullText 必须是字符串类型")
  }

  // 默认配置
  const {
    chunkSize = 5,
    interval = 50,
    onChunk = () => {},
    onFinal = () => {},
    onError = (err) => console.error("流式处理错误:", err),
  } = options

  // 验证配置参数的有效性
  if (!Number.isInteger(chunkSize) || chunkSize <= 0) {
    onError(new Error("chunkSize 必须是正整数"))
    return () => {} // 返回空的取消函数
  }

  if (!Number.isInteger(interval) || interval <= 0) {
    onError(new Error("interval 必须是正整数"))
    return () => {}
  }

  if (
    typeof onChunk !== "function" ||
    typeof onFinal !== "function" ||
    typeof onError !== "function"
  ) {
    onError(new Error("onChunk, onFinal 和 onError 必须是函数"))
    return () => {}
  }

  // 2. 状态变量初始化
  let currentPosition = 0
  let timer = null
  let isCanceled = false
  const textLength = fullText.length

  // 3. 核心处理函数(带错误捕获)
  const process = () => {
    if (isCanceled) return

    try {
      // 计算下一次要展示到的位置
      const nextPosition = Math.min(currentPosition + chunkSize, textLength)

      // 获取当前片段并更新位置
      const currentChunk = fullText.substring(0, nextPosition)
      currentPosition = nextPosition

      // 触发片段回调
      onChunk(currentChunk)

      // 检查是否已经完成所有文本的展示
      if (currentPosition >= textLength) {
        clearInterval(timer)
        timer = null
        onFinal(currentChunk) // 触发结束回调
      }
    } catch (err) {
      // 错误处理
      clearInterval(timer)
      timer = null
      onError(err)
    }
  }

  // 4. 启动流式处理(空文本特殊处理)
  if (textLength === 0) {
    // 空文本直接触发结束回调
    onChunk("")
    onFinal("")
    return () => {}
  }

  // 立即执行一次,然后设置定时器
  process()
  timer = setInterval(process, interval)

  // 5. 返回取消函数(确保资源正确释放)
  return () => {
    if (!isCanceled) {
      isCanceled = true
      if (timer) {
        clearInterval(timer)
        timer = null
      }
    }
  }
}
相关推荐
夏幻灵15 小时前
从语法坑点到 JS 内存底层:Vue 3 watch 侦听器深度全解
开发语言·javascript·vue.js
张元清15 小时前
React useFocus Hook:追踪并控制元素焦点状态 (2026)
javascript·react.js
Sterting16 小时前
反馈组件:对话框、消息与通知
前端·javascript·vue.js
breeze jiang16 小时前
ESLint flat config 配置实战:五大字段、规则严重级别与 --fix 能力边界详解
开发语言·前端·javascript
巴勒个啦16 小时前
ECharts 大屏开发实战:从布局设计到动画优化的完整流程
javascript
书中枫叶16 小时前
做了个「句拾」小程序,最难的不是业务,是字体
前端·javascript·vue.js
FFF_6345602316 小时前
简单的画板小工具,下载即用
前端·javascript·css
一朵好运莲16 小时前
智能体使用 Chrome DevTools MCP 调试浏览器
开发语言·javascript·react.js
sibylyue17 小时前
工作流表单和流程设计前端
开发语言·javascript·开源
用户5268356779017 小时前
Kafka 消费倾斜死锁与 Partition 掉队:我用 Rust 写了个“数据管道物理哨兵”,比 Grafana 报警快了 18 秒
javascript