Break for loop from inside of switch case in Javascript - javascript

What command I must use, to get out of the for loop, also from //code inside jump direct to //code after
//code before
for(var a in b)
{
switch(something)
{
case something:
{
//code inside
break;
}
}
}
//code after

You can use label. Have a labeled statement and break to that label. outerLoop is the label I have used here.
//code before
outerLoop:
for (var a in b) {
switch (something) {
case 'case1':
//code inside
break outerLoop;
}
}
//code after

use another variable to flag when you need to exit:
var b = { firstName: 'Peter', lastName: 'Smith' };
var keepGoing = true;
for (var a in b) {
switch (true) {
case 1:
keepGoing = false;
break;
}
if (!keepGoing) break;
console.log('switch end');
}
console.log('for end');
example

Unfortunately, Javascript doesn't have allow breaking through multiple levels. The easiest way to do this is to leverage the power of the return statement by creating an anonymous function:
//code before
(function () {
for (var a in b) {
switch (something) {
case something:
{
//code inside
return;
}
}
}
}());
//code after
This works because return leaves the function and therefore implicitly leaves the loop, moving you straight to code after
As pointed out in the comments, my above answer is incorrect and it is possible to multi-level breaking, as in Chubby Boy's answer, which I have upvoted.
Whether this is wise is, from a seven-year-later perspective, somewhat questionable.

it depends on what you want to accomplish... one thing I commonly do is something like this:
//code before
for(var a in b)
{
var breakFor = false;
switch(something)
{
case something:
{
//code inside
breakFor = true;
break;
}
}
if (breakFor)
break;
}
//code after

You can tell which loop / switch to break.
function foo ()
{
dance:
for(var k = 0; k < 4; k++){
for(var m = 0; m < 4; m++){
if(m == 2){
break dance;
}
}
}
}
See this answer.

for(var i=0; i<b.length; i++) {
switch (something) {
case 'something1':
i=b.length;
}
}
When the iteration variable i reaches the end of the loop, it breaks. But one can force the iteration variable to reach the end of the loop.

Replace your switch with a series of if statements.
for (const a of b) {
if (something === someValue) {
// code inside
break; // break out of the for loop
} else if (something === someOtherValue) {
// etc.
}
}

I always find using conditional statements one of the easiest ways to control the code flow, at least conceptually.
var done = false;
//code before for loop
for(var a in b){
switch(switchParameter){
case firstCase:
//code inside
done = true;
break;
}
}
if(done)
break;
}
//code outside of for loop

Related

Creating a loop for an else statement inside a function

I am trying to create a loop to include an else statement. It works perfectly with the if statement as below but when trying to put in the else statment it either shows nothing or creates 6 loops. Im assuming I am putting the else statement in the wrong place. Can someone please explain to me a) where to put the else statement and b) the nesting criteria of the ending curly braces inside a function
Heres what ive got and it works perfectly until i place the else statement in. thanks
var sports = ["golf", "cricket", "tennis", "badminton", "squash"];
function checkSport(sportToCheck) {
for (var i = 0; i <= sports.length; i++) {
if (sportToCheck == sports[i]) {
alert("yes we offer that sport");
}
}
}
checkSport("tennis")
Based on your variable names, I guess you don't have to use else in this context but you would like to end the loop/function as soon as the sport is found:
function checkSport(sportToCheck) {
for (var i = 0; i <= sports.length; i++) {
if (sportToCheck == sports[i]) {
alert("yes we offer that sport");
return; // stop the execution of the function
} else {
console.log("Do nothing so you don't need this else statement.");
}
}
alert("No we don't offer that sport"); // If the loop ends and cannot find any match
}
Because your function is check() and to respect Do One Thing rule, it's better to return true or false.
There are many ways to solve your issue but I prefer find().
var sports = ["golf", "cricket", "tennis", "badminton", "squash"];
function checkSport(sportToCheck) {
return sportToCheck === sports.find((sport) => sport === sportToCheck);
}
console.log(checkSport("football")); // Expect : false
console.log(checkSport("tennis")); // Expect : true
If you want to improve #Hangindev answer you can do this:
for (sport of sports) {
true === (sportToCheck === sport) && alert("yes we offer that sport");
}
No need for else statements. Simply run through each possible value in the sports array, and use the return statement to pause further script execution within that function.
The function returns either true or false depending on whether the string is inside the sports array.
var sports = ["golf", "cricket", "tennis", "badminton", "squash"];
function checkSport(sportToCheck) {
for (var i = 0; i <= sports.length; i++) {
if (sportToCheck == sports[i]) {
alert("yes we offer that sport");
return true;
}
if (i == sports.length) {
alert("sorry we do not offer this sport");
return false;
}
}
}
checkSport("tennis")
You could use this for something like:
if (checkSport("tennis")) {
// sport exists
} else {
// sport does not exist
}

js add event listener not working

I am trying to load interactivly some questins from questions' array (q) into my page and after student clicks at one of the 2 questions register the answer and change the question using js while loop. What is my mistake that it doesn't work?
var q = [
['NFR', 'Reusability'],
['NFR', 'Robustness'],
['FR', 'Reporting Requirements'],
['FR', 'Historical Data']
];
var correct = 0;
var incorrect = 0;
var total = q.length;
var i = 0;
document.getElementById('nick').innerText = name;
document.getElementById('question').innerText = q[0][1];
var nfr = document.getElementById('non-functional');
var fr = document.getElementById('functional');
function callback(ans) {
if (q[i][0] === ans) {
correct++;
} else {
incorrect++;
};
if (i < q.length - 1) {
i++;
document.getElementById('question').innerText = q[i][1];
} else {
location.href = "answer.html";
}
}
nfr.addEventListener('click', callback('NFR'));
fr.addEventListener('click', callback('FR'));
Your while loop is looping endlessly, because the only thing it does logically is set toNext to False, set some event listener callbacks and then evaluate toNext again, which will always be False. So i++ will never be called and i < q.length will always be True.
Get rid of the while loop. Write a separate function that evaluates the answer and updates your window with the next question. Use that function as callback for the click events.
In a callback function this will be set to the object calling the function, so you could write a function like this:
function callback() {
if (this.id == q[i][0]) {
window.correct++;
} else {
window.incorrect++;
}
i++;
set_question(i); // Logic to set the i-th question.
}
Edit
function callback(ans) {
// This function will return
// another function with the ans
// variable set, which in turn
// will be called as a callback
// when needed by the 'click' event.
return function () {
if (q[i][0] === ans) {
correct++;
} else {
incorrect++;
};
if (i < q.length - 1) {
i++;
document.getElementById('question').innerText = q[i][1];
} else {
location.href = "answer.html";
}
}
}
Event listeners are executed asynchronously and the code you write might assumes that the listeners can block loop execution.
To fix this, try removing the loop and move the logic of switching to the next question into the listener callback.

Break or continue loop within function calls

My question is: How can I trigger a break; or continue; for a loop through a function that gets called? The thing is, I do not want to nest all possible conditions within a loop to avoid code complexity. I was thinking about some pseudo example:
var someObjects = [...] //array with some js objects
for (var i = 0; i < someObjects.length; i++) {
var element = someObjects[i];
doSomething(element);
}
function doSomething(object) {
//some code here
if (somethingIsDefined) {
doSomethingElse(object);
}
}
function doSomethingElse(anotherObject) {
//some more code here
if (somethingMatches) {
//here i would like to break the most upper loop
}
}
//someObjects will be processed
I know that it would be possible to introduce for example a boolean variable and check within the loop if it is true or false and depending on that, break; or continue;.But this - even if it is just one line - would increase the nesting. Do you see any possible solutions?
If you are using the Underscore library, which I recommend, you could write the following:
_.any(someObjects, doSomething);
function doSomething(object) {
//some code here
return somethingIsDefined &&
doSomethingElse(object);
}
function doSomethingElse(anotherObject) {
//some more code here
return somethingMatches;
}

Javascript breaking a for loop inside a callback function

I have code like the following:
function test(obj) {
if(//some conditon) {
obj.onload();
}else{
obj.onerror();
}
}
for(var i=0;i<4;i++){
test({
onload:function(e){
//some code to run
},
onerror:function(e){
break;
}
});
}
The gist is the test() function is a function to make an XHR request (it is actually an API of the Appcelerator Titanium platform so I have no control over it) and I'm looping something to call the test function. I need to break the loop on the onerror function, but I get an error saying the break is not inside a loop or switch statement. How can I rewrite this?
If your code sample does represent some actual code (i.e. all the processing is done in the same event loop tick), you may do the following:
function test(obj) {
if (some_condition) {
return obj.onload();
} else {
return obj.onerror();
}
}
var result;
for(var i=0; i<4; i++){
result = test({
onload:function(e){
//some code to run
return true;
},
onerror:function(e){
return false;
}
});
if (!result) {
break;
}
}
Otherwise, if there is something asynchronous done, you have to call test sequentially, and not in parallel. For example,
function test(obj) {
doSomeAjaxRequest(arguments, function (err, result) {
if (some_condition) {
obj.onload();
} else {
obj.onerror();
}
});
}
var f = function (i) {
if (i >= 4) return;
test({
onload:function(e){
//some code to run
f(i+1);
},
onerror:function(e){
break;
}
});
}
f(0);
Not possible. A for loop is a synchronous procedure while an Ajax request is not. That means when the onerror callback happens, the for loop is already done executing.
As an alternative you could introduce a check into your onsuccess handler which confirms no errors have happened yet.
var errorOccured = false;
for(var i=0;i<4;i++){
test({
onload:function(e){
if(errorOccured) return;
//some code to run
},
onerror:function(e){
errorOccured = true;
}
});
}
Bit hacky maybe but one could do something like this with a handler function.
var handler = function(array, callback){
for(var i=0, l=array.length, e=array[i]; i<l; ++i){
if(true === handler.exit){
handler.exit = false; //restore
return;
}
callback.call(null, e);
}
};
handler.exit = false;
handler([1,2,3], function(e){
console.log(e);
if(2 === e){
arguments.callee.caller.exit = true; // :-)
}
});
Didn't test this but maybe you could bind function to scope in call even?
var handler = function(a, f){
this.exit = false;
for(var i=0, l=a.length, e=a[i]; i<l; ++i){
if(true === this.exit){
this.exit = false; //restore
return;
}
callback.call(this, e);
}
};
handler([1,2,3], function(e){
console.log(e);
if(2 === e){
this.exit = true;
}
});
You cannot break the loop inside test() function. I think the best solution in this case would be to throw an exception inside test() function, then catch it in the loop and break.
Maybe you can make the 'onload' callback recursive?
Meaning, you just call the 'test' method inside the 'onload' handlerr, this would also mean you fire all requests in order instead of all at the same time.
I take the answer of penartur, but I modified without the "break":
function test(obj) {
doSomeAjaxRequest(arguments, function (err, result) {
if (some_condition) {
obj.onload();
} else {
obj.onerror();
}
});
}
var f = function (i) {
if (i >= 4) return;
test({
onload:function(e){
//some code to run
f(i+1);
},
onerror:function(e){
console.log('stop');
}
});
}
f(0);

Something similar to jQuery when / then: deferred execution with break

I'm searching for a solution where I'm able to run different functions, but some of them need a timeout and all following functions need to wait until the previous one is finished. Every function should be able to break the complete process.
Now I thought pushing all functions to a stack and loop through them:
function foo() {
// bar() should wait as long the following is finished:
setTimeout(function(){
if ((new Date()).getSeconds() % 2) {
alert('foo');
// break loop through functions (bar is not called)
}
else {
// start next function (bar is called)
}
}, 1000);
}
function bar() {
setTimeout(function(){
alert('bar')
}, 1000);
}
var functions = new Array('foo', 'bar');
for (var i = 0, length = functions.length; i < length; i++) {
window[functions[i]]();
}
But how to include wait/break?!
Note: This should work with 2+ functions (amount of functions is changeable)
Note2: I don't want to use jQuery.
Note: I have updated my answer, see bottom of post.
Alright, let's take a look.
You're using the window[func]() method, so you should be able to store and use return values from each function.
Proof:
function a(){
return "value";
}
var ret_val = window['a']();
alert(ret_val);
Let's create a return rule:
If function returns true, continue execution flow.
If function returns false, break execution flow.
function a(){
//Do stuff
return (condition);
}
for(i = 0; i < n; i++){
var bReturn = window['function']();
if(!bReturn) break;
}
Now let's put it into practice.
function a(){
//Do stuff
return ((new Date()).getSeconds() % 2); //Continue?
}
function b(){
//Do stuff
return true; //Continue?
}
function c(){
//Do stuff
return false; //Continue?
}
function d(){
//Do stuff
return true; //Continue?
}
var functions = new Array('a', 'b', 'c', 'd');
for (var i = 0; i < functions.length; i++ ) {
var bReturn = window[functions[i]]();
if(!bReturn) break;
}
Depending on when you execute the script, eg, an even or uneven time period, it will only execute function a or execute functions a b & c. In between each function, you can go about your normal business.
Of course, the conditions probably vary from each individual function in your case.
Here's a JSFiddle example where you can see it in action.
With some small modification, you can for instance, make it so that if function a returns false, it will skip the following function and continue on to the next, or the one after that.
Changing
for (var i = 0; i < functions.length; i++ ) {
var bReturn = window[functions[i]]();
if(!bReturn) break;
}
To this
for (var i = 0; i < functions.length; i++ ) {
var bReturn = window[functions[i]]();
if(!bReturn) i++;
}
Will make it skip one function, every time a function returns false.
You can try it out here.
On a side-note, if you were looking for a waiting function that "pauses" the script, you could use this piece of code.
function pausecomp(millis){
var date = new Date();
var curDate = null;
do {
curDate = new Date();
}while(curDate-date < millis);
}
Update
After adjusting the code, it now works with setTimeout.
The idea is that you have an entry point, starting with the first function in the array, and pass along an index parameter of where you currently are in the array and then increment index with one to execute the next function.
Example | Code
function next_function(index){
if(index >= functions.length) return false;
setTimeout(function(){
window[functions[index+1]](index+1);
}, 1000);
}
function a(index){
//Do stuff
if(((new Date()).getSeconds() % 2)) return false; //Stop?
next_function(index);
}
function b(index){
//Do stuff
if(false) return false; //Stop?
next_function(index);
}
function c(index){
//Do stuff
if(true) return false; //Stop?
next_function(index);
}
function d(index){
//Do stuff
if(false) return false; //Stop?
next_function(index);
}
var functions = new Array('a', 'b', 'c', 'd');
//entry point
window[functions[0]](0);
This is exactly the scenario promises solve. In particular, the fact that promises can be broken is perfect for your situation, since a broken promise prevents the chain from continuing (just like a thrown exception in synchronous code).
Example, using the Q promise library discussed in the above-linked slides:
function fooAsync() {
return Q.delay(1000).then(function () {
if ((new Date()).getSeconds() % 2) {
alert("foo");
throw new Error("Can't go further!");
}
});
}
function barAsync() {
return Q.delay(1000).then(function () {
alert("bar");
});
}
var functions = [fooAsync, barAsync];
// This code can be more elegant using Array.prototype.reduce, but whatever.
var promiseForAll = Q.resolve();
for (var i = 0; i < functions.length; ++i) {
promiseForAll = promiseForAll.then(functions[i]);
}
// Of course in this case it simplifies to just
// promiseForAll = fooAsync().then(barAsync);
promiseForAll.then(
function () {
alert("done!");
},
function (error) {
alert("someone quit early!");
// and if you care to figure out what they said, inspect error.
}
).end();

Categories