前端模拟 流式文本接口 打字机效果 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
      }
    }
  }
}
相关推荐
Moment15 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
爱敲代码的小鱼15 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
铅笔侠_小龙虾17 小时前
Flutter 实战: 计算器
开发语言·javascript·flutter
大模型玩家七七17 小时前
梯度累积真的省显存吗?它换走的是什么成本
java·javascript·数据库·人工智能·深度学习
2501_9447114318 小时前
JS 对象遍历全解析
开发语言·前端·javascript
发现一只大呆瓜18 小时前
虚拟列表:支持“向上加载”的历史消息(Vue 3 & React 双版本)
前端·javascript·面试
阔皮大师19 小时前
INote轻量文本编辑器
java·javascript·python·c#
lbb 小魔仙19 小时前
【HarmonyOS实战】React Native 表单实战:自定义 useReactHookForm 高性能验证
javascript·react native·react.js
_codemonster19 小时前
Vue的三种使用方式对比
前端·javascript·vue.js
全栈前端老曹19 小时前
【MongoDB】Node.js 集成 —— Mongoose ORM、Schema 设计、Model 操作
前端·javascript·数据库·mongodb·node.js·nosql·全栈