Как ждать, пока речь не закончится внутри Loop? - PullRequest
4 голосов
/ 22 сентября 2019

Я хотел бы остановить / подождать цикл 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].Следующая sentences[i] не будет напечатана до тех пор, пока window.speechSynthesis.speak(audio) не будет закончена, после завершения речи будет напечатана sentences[i] для следующей итерации.

Так, как я могу заставить цикл ждать, покафункция не завершена?

Примечание: Я могу заставить его ждать в течение постоянного времени, но я хочу динамическое ожидание, то есть ожидание должно быть таким, чтобы window.speechSynthesis.speak(audio) требовало времени длязакончить текст.

Ответы [ 2 ]

3 голосов
/ 22 сентября 2019

Для SpeechSynthesisUtterance API существует событие onend, с которым вы можете играть ( SpeechSynthesisUtterance: конечное событие ).

Так что, я думаю, вы можете добавить прослушиватель событий к 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. Обещание
  2. SpeechSynthesis.speak ()
  3. SpeechSynthesisUtterance.onend
  4. асинхронная функция

Решение работает как шарм, надеюсь, это поможет!

1 голос
/ 22 сентября 2019

Существует также событие onstart, которое вы можете использовать следующим образом:

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 (или пусть) вместо 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');
...