javascript - 如何在回调期间从中删除事件监听器

标签 javascript audio popcornjs

我有一个带有一些 javascript 的页面,用于收听一系列音频文件中的一些故事。我使用爆米花库向特定时间戳添加脚注,在音频播放时突出显示页面文本中的单词。我有一个 javascript 对象 AudioPlayer (本例中的实例称为 ap),它包含许多音频元素和许多爆米花实例。音频元素第一次具有“loadedmetadata”时,如果我有该项目的时间戳,我想创建爆米花脚注。但是,我不想对给定的音频项目多次运行此函数。也就是说,人们可能会单击某个项目并重新加载它,但我不想重新创建时间戳。因此,我编写了这样的回调代码,以便在获取给定项目的时间戳时运行:

// try to load any timestamps for this file
this.loadTS = function(ann) { 
  var xhr = new XMLHttpRequest();
  xhr.open("GET", window.location.protocol+"//"+
                  window.location.hostname+"/sitename/timestamps/"+
                  window.location.pathname.substring(
                  window.location.pathname.lastIndexOf('/')+1)+".json",
            true);
  xhr.onreadystatechange=function(){
    if(xhr.readyState==4 && xhr.status==200){
      console.log(xhr.responseText);
      this.timestamps = JSON.parse(xhr.responseText);
      for(var idx in this.timestamps){

        var stampX = function(){ 
          // this is an audio element, get it's index to 
          // do the stamping  
          var x = window.ap.audios.indexOf(this);

          // need to remove this listner so it doesn't fire again!          
          this.removeEventListener('loadedmetadata',stampX); // <- fail :(
          // window.ap.audios[x]
          //  .removeEventListener('loadedmetadata',stampX);
          // ^^ this failed too :( :(

          // stamp away!
          window.ap.stampItem(window.ap.winIGTs[x], 
            window.ap.timestamps[x], window.ap.audios[x],
              window.ap.popcorns[x]);

        };

        this.audios[idx].addEventListener('loadedmetadata', stampX);

        if(ann) 
          this.textIGTs[idx].setAttribute("class","igt existstamps");
      }
    } else console.log(xhr.status);
  }.bind(this);
  xhr.send();
}

但我在测试此代码时发现,如果重新加载音频元素,“stampX”会再次被更多调用,因此我唯一的结论是,removeEventListener 不知何故没有获得与下面的 addEventListener 相同的引用。

我发现这很难调试。我无法将变量传递到 stampX 中,因为需要事件监听器的函数引用(而不是函数调用)。

无论如何,我很难找到正确的方法来编写此代码,以便我可以在第一次调用时间戳X时删除事件监听器。

最佳答案

看起来每次都会重新创建 stampX,因为您在 onreadystatechange 函数中声明了它。

这意味着您执行的每个 addEventListener 都会获得不同的回调函数。

您需要做的是分离它的逻辑,将其移到外部,更高的词法范围,例如您声明 xhr 对象的位置,甚至在 loadTS 减速之外。这样addEventListener和removeEventListener就会指向同一个函数。

关于javascript - 如何在回调期间从中删除事件监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39838540/

相关文章:

javascript - Javascript集合

javascript 有正则表达式问题

javascript - JS如何改变构造函数值

c# - 如何使用NAudio将音频文件转换为320kbps的.M4A?

javascript - 无法让 popcorn.js 工作

javascript - popcorn.js 可以检测切换视频并继续而不重新启动吗?

javascript - 为什么这些 JavaScript 函数只有一个起作用?

Java、Matlab 读取 Wav 文件中的数据,有何不同?

java - 用于上采样的 PCM 算法

ios - Mobile Safari - 等到 <video> 完全下载后再播放