audiojs icon indicating copy to clipboard operation
audiojs copied to clipboard

loading timer cannot clearinterval(fixed)

Open ume05rw opened this issue 11 years ago • 2 comments

I found timer-probrem, and fix it.

For example, When HTTP-Header's failure, audio.js element's "loadTimer" cannot clearInterval.

sample: http://dobes.jp/timer_cannot_clear/error     ↓ http://dobes.jp/timer_cannot_clear/fixed/

      trackLoadProgress: function(audio) {
        // If `preload` has been set to `none`, then we don't want to start loading the track yet.
        if (!audio.settings.preload) return;

        var readyTimer,
            loadTimer,
            audio = audio,
            ios = (/(ipod|iphone|ipad)/i).test(navigator.userAgent);

        // Use timers here rather than the official `progress` event, as Chrome has issues calling `progress` when loading mp3 files from cache.
        readyTimer = setInterval(function() {
          if (audio.element.readyState > -1) {
            // iOS doesn't start preloading the mp3 until the user interacts manually, so this stops the loader being displayed prematurely.
            if (!ios) audio.init.apply(audio);
          }
          if (audio.element.readyState > 1) {
            if (audio.settings.autoplay) audio.play.apply(audio);
            clearInterval(readyTimer);
            // Once we have data, start tracking the load progress.
            loadTimer = setInterval(function() {
              // ########## add console out ##########
              app.log("waiting load complete.");
              audio.loadProgress.apply(audio);
              if (audio.loadedPercent >= 1) clearInterval(loadTimer);
            }, 200);
          }
        }, 200);
        audio.readyTimer = readyTimer;
        audio.loadTimer = loadTimer;
      },
      trackLoadProgress: function(audio) {
        // If `preload` has been set to `none`, then we don't want to start loading the track yet.
        if (!audio.settings.preload) return;

        var // readyTimer, // ########## remove.
            // loadTimer,  // ########## remove.
            audio = audio,
            ios = (/(ipod|iphone|ipad)/i).test(navigator.userAgent);

        // Use timers here rather than the official `progress` event, as Chrome has issues calling `progress` when loading mp3 files from cache.

        // ########## set timer handle to audio's member direct. ##########
        audio.readyTimer = setInterval(function() {
          if (audio.element.readyState > -1) {
            // iOS doesn't start preloading the mp3 until the user interacts manually, so this stops the loader being displayed prematurely.
            if (!ios) audio.init.apply(audio);
          }
          if (audio.element.readyState > 1) {
            if (audio.settings.autoplay) audio.play.apply(audio);
            clearInterval(audio.readyTimer); // handle -> audio's member
            // Once we have data, start tracking the load progress.

            // ########## set timer handle to audio's member direct. ##########
            audio.loadTimer = setInterval(function() {
              // ########## add logging ##########
              app.log("waiting load complete.");
              audio.loadProgress.apply(audio);
              if (audio.loadedPercent >= 1) clearInterval(loadTimer);
            }, 200);
          }
        }, 200);

        //audio.readyTimer = readyTimer;  // ########## remove.
        //audio.loadTimer = loadTimer;    // ########## remove.
      },

ume05rw avatar Jul 07 '14 03:07 ume05rw

Freaky timing, thanks for picking up on this too. I'm in the process of adding support for event cleanup for instance destruction, and I notice that this timer isn't clearing either.

For the loadtimer, you also need to change the reference to: if (audio.loadedPercent >= 1) clearInterval(audio.loadTimer);

However, for me this condition is never met for some reason, and so the interval is never cleared, in my destroy() method, I'm trying to clear both audio.readyTimer and audio.loadTimer - but neither are clearing still.

EDIT: looking more closely at audio.loadTimer issue, it looks like audio.loadedPercent never reaches a value of 1 in Chrome, where it does in FF, so the interval is never cleared :(

FURTHER EDIT: It also looks like there can be multiple intervals running, so at least one never gets cleaned up. This can be a result of multiple calls to trackLoadProgress: container[audiojs].events.trackLoadProgress(audio);

Advisable to add in a check inside trackLoadProgress to only create audio.readyTimer and audio.loadTimer if they are not already created.

davewallace avatar Jul 08 '14 00:07 davewallace

I'm sorry, can't understand English well. Japanese study english six years, but...(- -;

I can show you my dispose method, add to container[audiojsInstance].prototype(line-598)

dispose: function(){
    //in play, stop it.
    if (this.playing){
        this.pause();
    }

    //in loading, clear timer.
    if (this.loadedPercent < 1) {
        if (!!this.loadTimer){
            clearInterval(this.loadTimer);
        }
        if (!!this.readyTimer){
            clearInterval(this.readyTimer);
        }
    }

    if (this.detachEvents){
        this.detachEvents();
    }

    //remove all <audio>tag.
    $(this.wrapper).find("audio").remove();

    _.each(this, function(v, k){
        delete this[k];
    }, this);
}

ume05rw avatar Jul 17 '14 06:07 ume05rw