在for循环中仅调用一次事件

时间:2015-11-06 21:45:53

标签: javascript

试图解决这个问题几个小时,我似乎无法找到解决方案。

基本上,我有一个使用HTML5的音频播放器。 音频播放时有一个事件监听器,每隔一秒触发一次,直到音频结束。

我根据API提供的时间戳在音频时间轴上生成标记,它看起来像这样。

enter image description here

此处有三个标记 - 如果总持续时间为60秒,我认为标记为5,10,29。

在每个标记之后,我需要从DOM上的API更改图像和段落文本,并使用jquery来执行此操作。

在#time; timeupdate'监听器,我有一个for循环,它遍历DOM上的每个标记,然后检查' currentTime' Audio对象的值小于' timestamp'。

 audioObject.addEventListener('timeupdate', () =>
 {
     for (let i = 0; i < $(options.markers).length; i++)
     {
         // If the current time of the audio is greater than the first timestamp second, continue
         if (options.audioObject.currentTime > options.podcastData[i].timestamp)
         {
             options.coverImage.attr('src', options.podcastData[i].image);
             options.theTitle.text(options.podcastData[i].name)
         }
     }

 }, false)

现在这样可行,但它每秒更新一次DOM,所以我看到Inspector Element上的闪烁,直到播客完成。

我需要的是只有在经过标记后才更新DOM一次,但目前我似乎找不到办法来做到这一点。

3 个答案:

答案 0 :(得分:1)

我做了两处修改:

  1. 按相反顺序浏览列表,并在匹配后退出。事实上,您不必要地设置和重置属性。
  2. 设置&#34;看到&#34;在您显示每个选项后对其进行归因。不要再显示两次。
  3.  for (let i = $(options.markers).length - 1; i >= 0; i--)
     {
         if (options.audioObject.currentTime > options.podcastData[i].timestamp)
         {
             if (! options.podcastData[i].seen)
             {
               options.coverImage.attr('src', options.podcastData[i].image);
               options.theTitle.text(options.podcastData[i].name)
               options.podcastData[i].seen = true
             }
    
             break
         }
     }
    

答案 1 :(得分:1)

每次事件触发时,您总是遍历整个标记列表,这意味着您将始终显示过去发生过的标记数据,并且之前已显示过。在您的示例中,在音频文件中29秒后,您将显示来自标记的数据,该数据以5秒的间隔以5秒的间隔发生,在此之后的每个间隔,标记在10秒处10秒间隔和之后的每个间隔和标记在29秒一次。每当您的事件发生时,您实际上都会显示并覆盖timestamp符合timestamp一个接一个的所有其他标记的每个标记。

如果您在阵列显示后从阵列中删除标记怎么办?一旦标记过去并且您更新了图像和标题,您就不需要在音频文件进展时再次显示它,因为您已经拥有(如果这样做,您可以随时恢复数组的缓存副本)标记,比方说,如果用户倒回流,如果可能的话。)

 audioObject.addEventListener('timeupdate', () => {
 for (let i = 0; i < $(options.markers).length; i++)
 {
     // If the current time of the audio is greater than the first timestamp second, continue
     if (options.audioObject.currentTime > options.podcastData[i].timestamp)
     {
         options.coverImage.attr('src', options.podcastData[i].image);
         options.theTitle.text(options.podcastData[i].name)

         // *** We've displayed this marker. No need to display it the next
         // time this event fires!
         options.markers = options.markers.splice(i, 1);
     }
 }

 }, false)

这样,每次事件发生时,您都不会经常显示旧标记的数据(然后使用其他标记的数据覆盖它们,等等)。

答案 2 :(得分:0)

尝试这样的事情:

if (options.theTitle.text()!=options.podcastData[i].name) options.theTitle.text(options.podcastData[i].name);

如果当前内容与您要显示的内容不同,则应仅更新内容。您可以使用与图像类似的语法,但我不想冒险键入它而不进行测试,我现在无法测试。

相关问题