You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js中window.speechSynthesis.getVoices页面刷新失效求助

问题原因分析
  1. SpeechSynthesis API的语音资源加载是异步过程,window.speechSynthesis.getVoices()仅在浏览器完成语音资源加载后才会返回有效列表。
  2. 首次加载时,浏览器可能已缓存语音资源,useEffect空依赖回调执行时资源已就绪,因此能正常获取数据;但页面刷新时,语音资源需要重新加载,此时useEffect执行过早,导致getVoices()返回空数组。
  3. 原代码未监听voiceschanged事件——该事件会在语音列表加载完成或发生变化时触发,无法捕获异步加载完成的时机。
解决方案

在useEffect中补充voiceschanged事件监听,确保语音资源加载完成后更新状态,同时适配Next.js的SSR特性(判断window存在性),并做好事件清理避免内存泄漏:

import { useState, useEffect } from 'react';

export default function Home() {
  const [voices, setVoices] = useState<SpeechSynthesisVoice[]>([]);

  useEffect(() => {
    const updateVoices = () => {
      if (window?.speechSynthesis) {
        setVoices(window.speechSynthesis.getVoices());
      }
    };

    // 先尝试获取一次,覆盖资源已提前加载的场景
    updateVoices();

    // 监听语音加载完成事件
    window.speechSynthesis.addEventListener('voiceschanged', updateVoices);

    // 组件卸载时清理监听
    return () => {
      window.speechSynthesis.removeEventListener('voiceschanged', updateVoices);
    };
  }, []);

  return (
    <div>
      <h1>可用语音列表</h1>
      <ul>
        {voices.map(voice => (
          <li key={voice.voiceURI}>{voice.name} ({voice.lang})</li>
        ))}
      </ul>
    </div>
  );
}

关键说明

  • updateVoices函数封装获取逻辑,通过window?.speechSynthesis判断避免Next.js服务端渲染时的报错。
  • 主动调用updateVoices处理首次加载时资源已就绪的情况。
  • voiceschanged事件监听确保在语音资源异步加载完成后更新状态,彻底解决刷新后返回空数组的问题。
  • 清理函数移除事件监听,防止内存泄漏。

内容的提问来源于stack exchange,提问作者hinsano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:11:20