0

I'll be short with words, here's the situation:

for (var _im = 0; _im < slideshow._preloadbulks[slideshow._preloadCurrentbulk].length; _im++) {
    var tmpSlideIndex = (slideshow._preloadCurrentbulk*slideshow._preloadMaxbulkSize)+_im;
    slideshow._preloadSlides[tmpSlideIndex] = document.createElement('video');
    slideshow._preloadSlides[tmpSlideIndex].autoplay = false;
    slideshow._preloadSlides[tmpSlideIndex].loop = false;
    slideshow._preloadSlides[tmpSlideIndex].addEventListener('canplaythrough', slideshow.slideLoaded, false);
    slideshow._preloadSlides[tmpSlideIndex].src = slideshow._slides[tmpSlideIndex][slideshow.image_size+"_video_url"];
    slideshow._preloadSlides[tmpSlideIndex].addEventListener('error', function(){
        console.log(tmpSlideIndex);
        slideshow._preloadSlides.splice(tmpSlideIndex,1);
        slideshow._slides.splice(tmpSlideIndex,1);
        slideshow.slideLoaded();
    }, true);
}

As you can see, I have a video array and I'm loading each element src to the DOM to pre-load it. It works just fine, but I have to deal with a situation when one resource is n/a, then I need to remove it from the existing arrays. The addEventListener('error', works just fine, it detects the unavailable resource but when I'm logging tmpSlideIndex into the console I get a different value rather than the original slide index (because the loop continues).

I've tried setting the useCapture flag as you can see to the error handler, thinking that will do the trick but it won't.

Any tricks? Thanks!

MaxArt
  • 22,200
  • 10
  • 82
  • 81
Gal Weissman
  • 208
  • 4
  • 11
  • possible duplicate of [Javascript closure inside loops - simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Bergi Apr 23 '13 at 12:39
  • Bergi, that's not even close. – Gal Weissman Apr 23 '13 at 12:40
  • @GalWeissman It *is* close, but you don't understand why. Which is pretty obvious, since you have posted this question. – MaxArt Apr 23 '13 at 12:42

1 Answers1

1

The issue is that when you are creating a closure over the tmpSlideIndex variable, it allows you to reference that variable inside the children function, but it's not creating a brand new variable, and since the loop continues and your error handler function executes asynchronously, the value of tmpSlideIndex will always be the last index of the loop. To keep the original value, we can create a self-executing function to wich we will pass the value of tmpSlideIndex. That self-executing function will effectively create a new scope and we will finally return a function that will create a closure over the slideIndex variable that lives in it's parent function scope.

slideshow._preloadSlides[tmpSlideIndex].addEventListener('error', (function(slideIndex) {
    return function () {
        console.log(slideIndex);
        slideshow._preloadSlides.splice(slideIndex,1);
        slideshow._slides.splice(slideIndex,1);
        slideshow.slideLoaded();
    };
})(slideIndex), true);
plalx
  • 42,889
  • 6
  • 74
  • 90