Why does the variable stays the same in Javascript?

59 Views Asked by At

I have an object, toKeep, where a MIDI note is contained in the label property of each object.

I want it to play after a certain delay depending on the number of notes that are received.

The problem now is that the variable pinned_neighbor stays the same even though it should change.

Is the problem that setTimeout function doesn't receive the data?

for (var ed = 0; ed < toKeep.length; ed++) {
    var pinned_neighbor = toKeep[ed].label

    if (pinned_neighbor != undefined) {
        setTimeout(function(pinned_neighrbor) {

            output.playNote(pinned_neighbor, parseInt(midi.substr(2, 2)));
            output.stopNote(pinned_neighbor, parseInt(midi.substr(2, 2)), { time: "+" + Math.floor(timefloor / toKeep.length) });
            console.log('playing an edge note ' + pinned_neighbor + ' at ' + timecodea + ' on ' + parseInt(midi.substr(2, 2)));
            timecodea = timecodea + Math.floor(timefloor / toKeep.length);

        }, timecodea);
    }
}
1

There are 1 best solutions below

0
On

You're not passing pinned_neighbor to setTimeout, and you can't do so the way you've written the code currently (as far as I know).

You'll need to use some sort of closure to retain the value of pinned_neighbor. You can use an IIFE or you can create another function that calls setTimeout.

IIFE Approach

for (...) {
    var pinned_neighbor = ...;
    if (pinned_neighbor != undefined) {
        // pn comes from the parameter pinned_neighbor passed at the bottom
        (function (pn) {
            setTimeout(function () {
                // Play note, etc
            }, timecodea);
        // Captures the value of pinned_neighbor
        })(pinned_neighbor);
    }
}

Separate Function

function playNote(pinned_neighbor, toKeepLength) {
    setTimeout(function () {
        // Play note using pinned_neighbor, etc
    }, timecodea);
}

// In your for loop
var pinned_neighbor = ...
if (pinned_neighbor != undefined) {
    playNote(pinned_neighbor, toKeep.length);
}