Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wait until speech is finished inside Loop?

I would like to halt/wait the for-loop until the window.speechSynthesis.speak(audio) finishes reading the text, then go to next iteration. I have below code:

 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)
         } 

Now what I want is that, once each sentences[i] is printed. The next sentences[i] will not be printed until window.speechSynthesis.speak(audio) is finished, once the speech is finished then the sentences[i] will be printed for the next iteration.

So how can I make the loop wait until a function is not finished?

Note: I can make it wait for a constant time, but I want a dynamic wait, i.e. the wait should be as long aswindow.speechSynthesis.speak(audio) takes time to finish the text.

like image 679
Consider Non-Trivial Cases Avatar asked Sep 22 '19 13:09

Consider Non-Trivial Cases


1 Answers

For SpeechSynthesisUtterance API there is an onend event what you can play with (SpeechSynthesisUtterance: end event).

So I guess you can add an event listener to onend where you need to call the next iteration's code. One good technique is to use Promise in asynchronous cases to wait until a callback finishes. I have created a working example for the above case from your question:

(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;
      });
    } 
  }
})();

If you are interested in more details, please go for the following links to read further:

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

The solution works just like charm, hope this helps!

like image 85
norbitrial Avatar answered Sep 22 '22 06:09

norbitrial