1

I'm trying to break a for-loop (labeled) from within a nested anonymous function, like this:

function ajax(iteration, callback) {
    var rtrn, xh;
    if (window.XMLHttpRequest) {
        xh = new XMLHttpRequest();
    } else {
        xh = new ActiveXObject("Microsoft.XMLHTTP");
    };
    xh.onreadystatechange = function() {
        if (xh.readyState == 4 && xh.status == 200) {
            callback(xh.responseText);
        };
    };
    xh.open("GET", "file.php?i=" + iteration, true);
    xh.send();
};

var atk_delay = 100;
loop:
for(i = 1; i <= 40; i++) {
    var to = atk_delay * i;
    setTimeout(
        function() {
            ajax(i, function(responseText) {
                var div = document.getElementById("combat");
                div.innerHTML += responseText;
                var arrRt = responseText.split("::");
                if(arrRt[0] == "stop") {
                    break loop;
                };
            });
        },
    to);
};

I really have no idea how to solve this. Obviously, the problem is that it cannot find the label. How can I resolve this?

7
  • I've edited the question since the label had the wrong name. Now the code is as I have it. Commented Nov 22, 2013 at 0:27
  • 4
    Are you aware that when you get to the point where you want to break it, the loop has already stopped? Commented Nov 22, 2013 at 0:30
  • setTimeout and ajax are obviously asynchronous, the logic inside the callback occurs after the loop has finished, and i gets lost due to the new scope. So there are two problems here, the "Infamous JavaScript Loop Problem" and the "How to return the response from an AJAX call" Commented Nov 22, 2013 at 0:35
  • ajax is asynchronous.... so loop might have made 4 more passes by the time you find your stop Commented Nov 22, 2013 at 0:36
  • 1
    Returning the responseText from my AJAX call works like a charm, but, no, I didn't realize that, @bažmegakapa. sighs Alright, I basically needs a complete new approach to this, I guess. Commented Nov 22, 2013 at 0:37

3 Answers 3

1

So I solved it! Thanks for the help guys! You got me to realize I needed a completely different approach!

function ajax(callback) {
    var rtrn, xh;
    if (window.XMLHttpRequest) {
        xh = new XMLHttpRequest();
    } else {
        xh = new ActiveXObject("Microsoft.XMLHTTP");
    };
    xh.onreadystatechange = function() {
        if (xh.readyState == 4 && xh.status == 200) {
            callback(xh.responseText);
        };
    };
    xh.open("GET", "file.php", true);
    xh.send();
};

var atk_delay = 100;

function roll() {
    ajax(function(responseText) {
        var div = document.getElementById("combat");
        div.innerHTML += responseText;
        var arrRt = responseText.split("::");
        if(arrRt[0] == "cont") {
            setTimeout(roll, atk_delay);
        };
    });
};

setTimeout(roll, atk_delay);
Sign up to request clarification or add additional context in comments.

3 Comments

Never pass a string to setTimeout - it's the same as calling eval on it, with all the problems it brings to the table. Always pass a function reference instead, like setTimeout(roll, atk_delay);.
Oh, I had no idea! Thanks!
@kapa I see that the solution solves the problem by avoiding the problem. It's a good solution, but doesn't really match the question title. I have a different problem that has a similar question title but your solution doesn't really work for me. I know that you didn't do anything wrong; I'm just saying.
0

Normally what you would do is have a variable that's accessible after each iteration of the loop that would indicate if you can break. This would be set in the anonymous function.

However, in your specific case, since you are calling setTimeout, execution of the loop might have been completed by the time you can even set the value. setTimeout schedules the function to later execution (in ms).

You can use a variable to exit the anonymous function early if something has flagged it as done.

3 Comments

I just realized that. I honestly missed that completely. I blame the late hour here in Sweden. Maybe instead I could use a recursive function?
That would work well; you could not execute the next step at all instead of trying to break when needed.
I posted my solution as an anwer! Thanks for your time and help! :-)
0

A simple hack to debug anonymous blocks - call the debugger explicitly before the line you want to examine.

function foo().then(s => {
  ... some code
  debugger // here your code will break. 
  someVariableIwantToExamine
}

Comments

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.