0

I'm trying to execute some statements with setTimeout, inside the function plotReglaFalsa which is actually executed as callback at getSendingJSON("/plot",args,plotReglaFalsa)

This is is code snippet where sentences are executed by setTimeout:

for (series in respuesta) {
                if (series != "x" && series != "y" && series != "raiz") {

                    setTimeout(function(respuesta,series){plot.highlight(c,[respuesta[series].a,0])},1500)                      
                    setTimeout(function(respuesta,series){plot.highlight(c,[respuesta[series].b,0])},1800)  
                    c++
                }
}

The issue here is that respuesta and so series are actually existing once the callback happens.

When I try to run I get the following console outputs:

TypeError: series is undefined


...Timeout(function(respuesta,series){plot.highlight(c,[respuesta[series].a,0])},15...

16
biseccion.js (line 50)
TypeError: series is undefined


...Timeout(function(respuesta,series){plot.highlight(c,[respuesta[series].b,0])},18...

This is my whole code:

function plotReglaFalsa(respuesta) {

            var result = []

            result.push({
            label: "fx",
            color: "red",
            data: _.zip(respuesta['x'], respuesta['y'])
            })

            for (series in respuesta) {
                if (series != "x" && series != "y" && series != "raiz") {
                    result.push({
                        color: "blue",
                        data: [[]]
                    })
                }
            }

            var plot = $.plot(  $("#placeholder"), 
                                result, 
                                {   selection:{mode: "xy"},  
                                    zoom: { interactive: true }, 
                                    pan: { interactive: true }, 
                                    grid: { markings: [{ xaxis: { from: 0.0, to: 0.0 }, color: 'black', lineWidth: 2 }, { yaxis: { from: 0.0, to: 0.0 }, color: 'black', lineWidth: 2 }] }
                                })
            plot.getOptions().selection.mode = null

            var c = 1

            for (series in respuesta) {
                if (series != "x" && series != "y" && series != "raiz") {

                    setTimeout(function(respuesta,series){plot.highlight(c,[respuesta[series].a,0])},1500)
                    setTimeout(function(respuesta,series){plot.highlight(c,[respuesta[series].b,0])},1800)
                    c++
                }
            }

        }

        getSendingJSON("/plot",args,plotReglaFalsa)


            function resaltarPuntos(plot,respuesta,series,c,x){
            plot.highlight(c,[respuesta[series].x,0])
        }

        function desResaltarPuntos(plot){
            plot.unhighlight()
        }

getSendingJSON is actually AJAX. How can I get this completed?

10
  • 1
    possible duplicate of Javascript infamous Loop issue? Commented Feb 25, 2014 at 3:26
  • You're passing your functions to setTimeout(), so the setTimeout() is going to invoke them. Yet they have no idea what the variables are that you want, so they have no way to pass them to the functions. Defining function parameters doesn't somehow cause them to be passed to the function. Commented Feb 25, 2014 at 3:33
  • 1
    JSHint will give you a couple warnings -- "Don't make functions within a loop" Commented Feb 25, 2014 at 3:35
  • 1
    ...modern JS engines will let you pass the data you want directly to setTimeout. Like: setTimeout(function(respuesta,series){/*...*/}, 1500, respuesta, series); Won't work in older browsers though. Commented Feb 25, 2014 at 3:37
  • @cookiemonster I'm using last Firefox version Commented Feb 25, 2014 at 3:39

1 Answer 1

1

as per elclanrs' comment:

every time the code iterates through the for loop it modifies the value of series. so by the time your setTimeout() is called, the value of series has been updated to the last value in respuesta.

You need to utilize a closure so your setTimeout() uses the value of series as it was during that iteration.

for (series in respuesta) {
    if (series != "x" && series != "y" && series != "raiz") {
        (function(x){
            setTimeout(function(){plot.highlight(c,[respuesta[x].a,0])},1500);                     
            setTimeout(function(){plot.highlight(c,[respuesta[x].b,0])},1800);
            c++;
         }(series))
    }     
}
Sign up to request clarification or add additional context in comments.

8 Comments

This will only work if you remove the parameters from the anonymous functions passed to setTimeout().
Actually, the intent is to avoid the consequences of closures by assigning the value to a different variable that is not updated by the loop.
Is that why anonymous function receives x?
@diegoaguilar—yes. The value of series in the loop is passed to x, which is then available to the function passed to setTimeout. A new instance of x is created on each loop for each function, avoiding the consequences of multiple references to the one instance of series.
@diegoaguilar: The respuesta,x parameters need to be removed from the functions being passed in order for this technique to work. setTimeout(function(){...
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.