Search code examples
javascripttext-to-speechspeech-synthesisspeechsynthesizer

window.speechSynthesis.speak won't speak unless no other command remains incomplete


I'm trying to write test code in javascript where I try to log and pronounce a random number at the same time. For text to speech I use SpeechSynthesisUtterance with window.speechSynthesis:

function generate(){
 for (let i = 0;i<100;i++){
   let randomNumber = numberGenerator.generateNumber();
   showAndSayIt(randomNumber);
 }
}


const showAndSayIt = (m) => {
    var msg = new SpeechSynthesisUtterance(m);
    console.log(m);
    window.speechSynthesis.speak(msg);
}

When I run this code, I get all the logs immediately and only after everything is complete, I start hearing 100 speeches one by one. So it seems like all the speeches generated get accumulated and then when there's no other command to accomplish the speech generator spits all of them at once. Is there a way to change this behavior and be able to pronounce the speech in its right order?

I've tried it with Google Chrome 75.


Solution

  • Your analysis is correct that the speak commands are only run once all the console.logs are complete. This is because, as an API, speechSynthesis methods (e.g. speak()) get put into the browser's task queue to wait until the call stack is clear i.e. all the console.logs have finished. Here's a good video.

    If you want something to happen at the same time as something that goes into the task queue then you can use an event. In this case the Utterance has onstart and onend, depending if you want it to happen just before or just after the speech.

    So assuming you want the console.log to occur just before the speech you can use this code. But if you want it to happen after change onstart to onend.

    const showAndSayIt = (m) => {
        const msg = new SpeechSynthesisUtterance(m);
        msg.onstart = () => console.log(m);
        speechSynthesis.speak(msg);
    }