Представление Angular 6 не обновляется даже с помощью ChangeDetectorRef, ngZone и requestAnimationFrame

В моем файле component.ts есть цикл, который преобразует аудиоданные WAV в MP3:

for (var i = 0; i < samples.length; i += sampleBlockSize) {

  let sampleChunk = samples.subarray(i, i + sampleBlockSize);
  var mp3buf = mp3encoder.encodeBuffer(sampleChunk);
  if (mp3buf.length > 0) {
      mp3Data.push(mp3buf);
  }

  this.convertedPercent = Math.floor( ( i / samples.length ) * 100);
  console.log('convertedPercent: ' + this.convertedPercent);
}

console.log('This is where the HTML view jumps from 0% to 100%');

В моем component.html есть код, который показывает, какой процент аудио уже преобразован:

<p>Conversion is {{ convertedPercent }}% complete</p>

Во время преобразования он регистрирует правильный процент преобразования в консоль в режиме реального времени, однако представление остается на уровне завершения 0 %. Как только цикл заканчивается, он мгновенно переходит на 100%.

Я пытался:

  • this.cd.detectChanges();
  • перенос строки, которая изменяет значение convertedPercent в zone.run()
  • перенос строки, которая изменяет значение convertedPercent в requestAnimationFrame()

Что же мне попробовать дальше?


person Derrick Miller    schedule 10.11.2018    source источник
comment
Я подозреваю, что вам нужно выделить часть времени для каждой итерации, возможно, попробуйте setTimeout(). freecodecamp.org/forum/t/   -  person Joseph Wu    schedule 10.11.2018
comment
На самом деле, я тоже пробовал, и это не помогло :-(   -  person Derrick Miller    schedule 10.11.2018
comment
Было бы проще дать исправление, если бы вы могли создать образец демо в stackblitz.   -  person Sunil Singh    schedule 10.11.2018
comment
Вы когда-нибудь находили решение своей проблемы?   -  person new_programmer_22    schedule 15.07.2019
comment
@newwebdev22: Нет, не знал. Я считаю, что ответ Суреша правильный - этого невозможно добиться, не перенося логику преобразования в веб-воркер.   -  person Derrick Miller    schedule 17.07.2019


Ответы (1)


Как мы знаем, Javascript является однопоточным. Если вы выполняете тяжелые вычисления, ваш основной поток будет заблокирован и не будет освобожден до тех пор, пока он не завершится. Может быть, вы можете попробовать с Observables, с асинхронной операцией браузер будет обрабатывать ее в зависимости от приоритета.

Компонент:

convertedPercent$ = new Subject<any>();
convertedPercent$.next(this.convertedPercent);

Шаблон:

<p>Conversion is  {{ convertedPercent$ | async }}% complete</p>
person Suresh Kumar Ariya    schedule 10.11.2018
comment
Я попробовал это, и результат аналогичен. В представлении отображается только завершение преобразования в % во время выполнения цикла, а затем, когда оно завершается, оно изменяется на завершение преобразования на 100 %. Я думаю, что вы можете быть правы в том, что основной поток заблокирован. Это имеет большой смысл. - person Derrick Miller; 10.11.2018
comment
Вы можете переместить эту логику преобразования в веб-воркеры (отдельный поток) и обновить статус в основной поток, используя window.postMessage - person Suresh Kumar Ariya; 10.11.2018
comment
Это имеет смысл. Я постараюсь реализовать это и сообщу здесь о результатах. Спасибо за вашу помощь! - person Derrick Miller; 10.11.2018