如何使用Web Speech API逐行朗读textarea内容并加行间延迟,修复循环重复问题
问题根因
- 你用
var声明循环变量i,存在变量提升的作用域问题,同步的for循环会瞬间执行完毕,等异步的语音朗读API实际执行取值时,i已经等于数组长度,读到的永远是最后一行内容 - 没有处理朗读的异步时序,直接在循环里调用
speak会把所有语音请求瞬间塞进队列,也实现不了相邻行之间5秒延迟的需求 - 循环内部重复获取textarea值、重复拆分数组属于冗余逻辑,没有实际作用
修复后完整代码
document.querySelector("#start").addEventListener("click", async () => { // 若你已经在外部初始化过speech实例可以删掉下一行 const speech = new SpeechSynthesisUtterance(); const textInput = document.getElementById("textarea"); // 后面的filter是过滤空行,不需要可以直接删掉 const textArray = textInput.value.split(/\n/g).filter(item => item.trim()); // 封装延迟工具函数 const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); for (let i = 0; i < textArray.length; i++) { // 等待上一条语音完全朗读结束 while (window.speechSynthesis.speaking) { await delay(100); } speech.text = textArray[i]; window.speechSynthesis.speak(speech); // 如果最后一行不需要加5秒延迟,可以给这行加判断:if(i !== textArray.length - 1) await delay(5000); } });
关键改动说明
- 循环变量改用
let声明,基于块级作用域特性避免异步执行时变量值被覆盖 - 引入async/await+延迟函数控制执行时序,既实现了两行朗读之间5秒的间隔要求,也增加了播放状态检测逻辑,避免出现前一行还没读完就开始加载下一行的异常
- 移除循环内重复获取DOM、重复拆分文本的冗余逻辑,统一在循环前处理一次即可
- 新增可选的空行过滤逻辑,避免空内容触发无意义的朗读和等待,不需要可自行删除相关代码
内容的提问来源于stack exchange,提问作者erskyne
相关产品推荐
相关产品推荐

