如何等到循环内的语音结束?

How to wait until speech is finished inside Loop?

我想 halt/wait for 循环直到 window.speechSynthesis.speak(audio) 完成阅读文本,然后转到下一次迭代。我有以下代码:

 var all = "Oak is strong and also gives shade \n \
    Cats and dogs each hate the other \n \
    The pipe began to rust while new \n Bye."


 sentences = all.split('\n')
      for (i = 0; i < sentences.length; i++) {
        sentence = sentences[i]
        console.log(sentences[i]);
        audio = new SpeechSynthesisUtterance(sentence)
        window.speechSynthesis.speak(audio)
         } 

现在我想要的是,每个 sentences[i] 打印一次。在window.speechSynthesis.speak(audio)完成之前不会打印下一个sentences[i],一旦演讲结束,将在下一次迭代中打印sentences[i]

那么我怎样才能让循环等到一个函数没有完成呢?

注意:我可以让它等待一个恒定的时间,但我想要一个动态等待,即等待时间应该与window.speechSynthesis.speak(audio)需要的时间一样长完成正文。

对于 SpeechSynthesisUtterance API 有一个 onend 事件你可以玩 (SpeechSynthesisUtterance: end event)。

所以我想您可以在 onend 中添加一个事件侦听器,您需要在其中调用下一次迭代的代码。一种好的技术是在异步情况下使用 Promise 来等待回调完成。我根据你的问题为上述案例创建了一个工作示例:

(function() {
  play();

  async function play() {
    let all = "Oak is strong and also gives shade \n \
              Cats and dogs each hate the other \n \
              The pipe began to rust while new \n Bye.";

    sentences = all.split('\n');

    for (i = 0; i < sentences.length; i++) {
      await getNextAudio(sentences[i]);
    }

    async function getNextAudio(sentence) {
      console.log(sentence);
      let audio = new SpeechSynthesisUtterance(sentence);
      window.speechSynthesis.speak(audio);

      return new Promise(resolve => {
        audio.onend = resolve;
      });
    } 
  }
})();

如果您对更多细节感兴趣,请访问以下链接进一步阅读:

  1. Promise
  2. SpeechSynthesis.speak()
  3. SpeechSynthesisUtterance.onend
  4. async function

该解决方案非常有效,希望对您有所帮助!

还有一个启动事件,您可以像这样使用它:

for (i = 0; i < sentences.length; i++) {
  const sentence = sentences[i];
  const audio = new SpeechSynthesisUtterance(sentence);
  audio.onstart = () => console.log(audio.text);
  speechSynthesis.speak(audio);
}

或稍短:

for (const sentence of sentences) {
  const audio = new SpeechSynthesisUtterance(sentence);
  audio.onstart = () => console.log(audio.text);
  speechSynthesis.speak(audio);
}

PS 您可以修改代码的顶部以使用 const(或 let)代替 var,如下所示:

const all = "Oak is strong and also gives shade \n \
    Cats and dogs each hate the other \n \
    The pipe began to rust while new \n Bye.";
const sentences = all.split('\n');