Почему SpeechSynthesisUtterance иногда не запускает событие 'end' в браузерах на основе Chromium? - PullRequest
0 голосов
/ 25 февраля 2019

И в Chrome (v72, W10), и в Opera следующий фрагмент очень редко , похоже, не запускает подключенного end прослушивателя к SpeechSynthesisUtterance, может быть, 1из 50 раз выполняется фрагмент.(Извините, в оригинальной версии это можно было бы воспроизвести гораздо проще - теперь создание высказывания по нажатию кнопки, похоже, сделало ошибку намного более редкой)

button.onclick = () => {
  console.log('start script');
  button.disabled = true;
  const utt = new SpeechSynthesisUtterance('e');
  utt.addEventListener('end', () => {
    console.log('end event triggered');
  });

  // just for debugging completeness, no errors seem to be thrown though
  utt.addEventListener('error', (err) => {
    console.log('err', err)
  });

  speechSynthesis.speak(utt);
  setTimeout(() => {
    console.log('finished?');
  }, 1500);
};
<button id="button">click</button>

Из того, что я видел, если событие end когда-либо активируется, оно будет всегда активироваться в пределах данной загрузки страницы, чтоВот почему я отключил кнопку в приведенном выше фрагменте.(вам придется многократно перезапускать фрагмент, чтобы увидеть проблему)

Вы можете воспроизвести его с большей готовностью, запустив приведенный ниже фрагмент в Chrome (72 на W10) с отключенными ограничениями автоигры.(перейдите к chrome://flags/, измените Политика автозапуска на Жест пользователя не требуется ).

(В Opera, кажется, так же трудно воспроизвести, как впервый фрагмент, к сожалению)

console.log('start script');
function say(text) {
  const utt = new SpeechSynthesisUtterance(text);
  utt.addEventListener('end', () => console.log('end: ' + text));
  
  // just for debugging completeness, no errors seem to be thrown though
  utt.addEventListener('error', (err) => {
    console.log('err on ' + text + ', ', err)
  });
  
  speechSynthesis.speak(utt);
}

say('foo');
say('bar');

Firefox (56), насколько я вижу, не имеет этой проблемы - в нем слушатель end всегда срабатывает правильно.

AmЯ как-то не правильно прикрепляю слушателя, или это ошибка Chromium?

1 Ответ

0 голосов
/ 08 марта 2019

Редактировать / обновить : @Ouroborus указал, что это действительно ошибка открытого хрома


Я загорелся Sawbuck и начал попытки воспроизвести это.Когда возникает проблема, я постоянно вижу, как между «запускается скрипт» и «завершается?» Происходит действие gc.logs.

Пример успеха:

enter image description here

Пример сбоя:

enter image description here

Итак, может показаться, что процесс gc мешает доставляемому событию end.

Для дальнейшего тестирования этой теории я запустил Chrome с --js-flags="--expose-gc"флаг, который включает функцию v8 gc, позволяющую принудительно собирать мусор.

Если я изменю ваш тестовый код и добавлю window.gc() до console.log('start script'), я больше не смогу воспроизвести проблему (> 50 попыток).Возможно, это потому, что он уменьшает / исключает вероятность того, что gc возникает во время речевого высказывания.

Похоже, что вы можете предотвратить SpeechSynthesisUtterance объект от gc'dconsole.log -ing это.Это, кажется, приводит к последовательной доставке события.Очевидно, что предотвращение их коллекции, вероятно, не идеально, если вы создаете множество таких объектов:

button.onclick = () => {
  console.log('start script');
  button.disabled = true;
  const utt = new SpeechSynthesisUtterance('e');
  
  // Prevent garbage collection of utt object
  console.log(utt);

  utt.addEventListener('end', () => {
    console.log('end event triggered');
  });

  // just for debugging completeness, no errors seem to be thrown though
  utt.addEventListener('error', (err) => {
    console.log('err', err)
  });

  speechSynthesis.speak(utt);
  setTimeout(() => {
    console.log('finished?');
  }, 1500);
};
<button id="button">click</button>
...