addEventListener () вызывается только в последнем цикле цикла - PullRequest
0 голосов
/ 27 ноября 2018

Я пытался решить эту проблему часами, но безуспешно.Просматривал все похожие вопросы, задаваемые на stackoverflow, но ни одно из решений, похоже, не работает для меня.

У меня есть множество видео, которые я просматривал.Мне нужно подключить каждое видео к аудиоэлементу, чтобы быстро определить его продолжительность и точное время, когда оно появляется в списке воспроизведения.

То, что у меня изначально было, это:

// Set time in playlist for each video
for (let index=0; index<this.playlist.length; index++) {
  var audio = document.getElementById('audio');
  console.log('INDEX: ' + index);
  self.playlist[index].timeInPlaylist = [];
  self.playlist[index].duration = 0;
  audio.setAttribute('src', self.playlist[index].bucketRef);
  audio.addEventListener('canplaythrough', function(e){
     videoDuration = Math.round(e.currentTarget.duration);
     console.log("Duration of video number " + index + ": " + 
     videoDuration + " seconds");
     self.playlist[index].duration = videoDuration;
     self.playlist[index].timeInPlaylist[0] = playlistLength;
     playlistLength = playlistLength + videoDuration;
     self.playlist[index].timeInPlaylist[1] = playlistLength;
  });
};

Запускэтот код оставлял индекс таким же, а на выходе была длина последнего видео в массиве, записанного 3 раза.Затем, покопавшись в ней, я понял, что мне нужен какой-то тип закрытия из-за добавления прослушивателей событий внутри цикла.Поэтому я провел небольшой рефакторинг и пришел к этой текущей версии:

function log(e, index) {
  videoDuration = Math.round(e.currentTarget.duration);
  console.log("Duration of video number " + index + ": " + videoDuration + " seconds");
  self.playlist[index].duration = videoDuration;
  self.playlist[index].timeInPlaylist[0] = playlistLength;
  playlistLength = playlistLength + videoDuration;
  self.playlist[index].timeInPlaylist[1] = playlistLength;
}

// Set time in playlist for each video
for (let index=0; index<this.playlist.length; index++) {
  var audio = document.getElementById('audio');
  console.log('INDEX: ' + index);
  self.playlist[index].timeInPlaylist = [];
  self.playlist[index].duration = 0;
  audio.setAttribute('src', self.playlist[index].bucketRef);
  debugger;
  (function() {
      var i = index;
      audio.addEventListener("canplaythrough", function(e) { log(e, i); });
  })();
};

Это решило мою проблему с индексами;однако, я все еще получаю только длительность последнего видео в массиве.

консольный вывод

Я был бы очень признателен за некоторые отзывы.Эта проблема убивает меня.

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

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

После завершения цикла и аудиоэлемента загружает аудио дляпоследний атрибут src, с которым он был установлен, все прослушиватели событий вызываются с деталями одного и того же последнего элемента списка воспроизведения.

Вам нужно будет изменить дизайнкод для асинхронного запуска и последовательной загрузки одного аудиоэлемента с разными аудиоисточниками или создания нового элемента AUDIO для каждого элемента списка воспроизведения.В качестве альтернативы оставьте поле длительностью пустым, пока пользователь не выберет элемент для воспроизведения (просто мысль).

Обратите внимание, что вам не нужно создавать замыкание для хранения значения index - это ошибка в отладке: let в объявлении цикла for index создает отдельную лексическую ссылку на переменную для каждой итерации цикла.Значение index, видимое в выражении функции в цикле, соответствует значению итерации, когда выражение было оценено.

0 голосов
/ 27 ноября 2018

Вы создали замыкание, но неверным образом.

Замените эту часть в коде кода

(function() { var i = index; audio.addEventListener("canplaythrough", function(e) { log(e, i); }); })();

на

audio.addEventListener("canplaythrough", (function(audioObj, index) {
    return function(){
      log(audioObj, index); 
    }
  })(this, index)
 );

Это должно дать вам прямой доступ к аудиообъекту внутри функции log , чтобы получить его продолжительность, а не полагаться на объект события.

...