简体   繁体   中英

How to properly add addeventlistener?

I try add to array with image event listener which catch load event and it's works. But sometimes i parameter passed to the decrement function is the same for all requests

var imgNumb = vectors.length;
function decrement(i, type){
    imgNumb--;
    console.log('Processed '+ type+' nr: ' + i + '. Left: '+ imgNumb);
}
for(var i in vectors)
{
    if(jQuery('#canvas-'+i).length != 0){
    var tempCont = document.getElementById('canvas-'+i);
    tempImage[i] = new Image();
    alert(i);
    tempImage[i].addEventListener('load', function(){
        decrement(i, 'canvas');
    }, false);
    type[i] = 'canvas';
       tempImage[i].src = tempCont.toDataURL();
    }
}

for example i get:

Processed canvas nr: 1. Left: 2
Processed canvas nr: 2. Left: 1
Processed canvas nr: 2. Left: 0

but alert (if it isn't inside handler) always return correct key number.

You are creating a function in a loop which is dependent on the loop variable. All functions reference the same i . You have to introduce a new scope (by calling a function) to capture the current value of the variable:

(function(index) {
    tempImage[index].addEventListener('load', function(){
        decrement(index, 'canvas');
    }, false);
}(i));

Here we use an immediate or self-invoking function .


Don't use for...in to iterate over arrays . Use a normal for loop.

@Felix's answer is correct, but I thought I might show an alternative solution that might be more readable:

var imgNumb = vectors.length,
    tempImage = [];

function decrement(i, type) {
    imgNumb--;
    console.log('Processed ' + type + ' nr: ' + i + '. Left: ' + imgNumb);
}

$.each(vectors, function(i, element) {
    var $canvas = $('#canvas-' + i);
    if ($canvas.length) {
        tempImage[i] = $('<img/>', {
            src: $canvas.get().toDataURL(),
            load: function() {
                decrement(i, 'canvas');
            }
        });
        type[i] = 'canvas';
    }
});

It's not clear in the question if vectors is a jQuery object or a plain JS array, so I've taken the safe assumption and used $.each() . If vectors is a jQuery object, you can use .each() instead.

Other fixes:

  • Don't use for... in to iterate over arrays.
  • Just check the truthiness of jQuery('#canvas-' + i).length
  • You're using jQuery - why use document.getElementById() ?
  • Again, you're using jQuery - why use addEventListener() ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM