Break a for loop from within an anonymous function - javascript

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?

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);

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.

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
}

Related

async and set timeout

I am having some problem using the settimeout() in my function. I am new to async. No matter how much I try I just can't make the timeout work. My code works perfect so that is not the problem. I need the request to execute every 10 seconds. Thanks for the help.
function getContent() {
function getPelicula(pelicula, donePelicula) {
var peli = pelicula.title;
//request id
request({
url: "http://api.themoviedb.org/3/search/movie?query=" + peli + "&api_key=3e2709c4c051b07326f1080b90e283b4&language=en=ES&page=1&include_adult=false",
method: "GET",
json: true,
}, function(error, res, body) {
if (error) {
console.error('Error getPelicula: ', error);
return;
}
var control = body.results.length;
if (control > 0) {
var year_base = pelicula.launch_year;
var id = body.results[0].id;
var year = body.results[0].release_date;
var d = new Date(year);
var year_solo = d.getFullYear();
if (year_base == year_solo) {
pelicula.id = id;
pelicula.year_pagina = year_solo;
}
} else {
pelicula.id = null;
pelicula.year_pagina = null;
}
donePelicula();
});
}
}
To do something in a loop, use setInterval.
UPD:
In general, there're two ways of executing some code in loop
1 setTimeout :
var someTimer = setTimeout(function sayHello(){
console.log("hello!");
someTimer = setTimeout(sayHello, 2000);
}, 2000);
Notice that someTimer variable is needed to stop the looping process if you need: clearTimeout(someTimer)
2 setInterval:
var someIntervalTimer = setInterval(function(){
console.log("I'm triggered by setInterval function!");
}, 2000);
Invoke clearInterval(someIntervalTimer) to stop the looping
Both functions are treated as properties of the global Window variable. By default, the following code works:
var window = this;
console.log("type of setTimeout: " + typeof window.setTimeout);
console.log("type of setInterval: " + typeof window.setInterval);
Try putting it in another function so:
domore(pelicula,donePelicula);
function domore(pelicula,donePelicula) {
// 1 second
var timeout = 1000;
for (var i = 1; i < pelicula.length; i++) {
createData(pelicula[i],donePelicula,timeout);
timeout = timeout + 800;
}
}
function createData(peli,donePelicula,timeout) {
setTimeout(function() { getData(peli,donePelicula); }, timeout);
}
function getData(peli,donePelicula) {
var txtFile = new XMLHttpRequest();
txtFile.open("GET", "http://api.themoviedb.org/3/search/movie?query=" + peli + "&api_key=3e2709c4c051b07326f1080b90e283b4&language=en=ES&page=1&include_adult=false", true);
txtFile.onreadystatechange = function() {
if (txtFile.readyState === 4) { // Makes sure the document is ready to parse.
if (txtFile.status === 200) { // Makes sure it's found the file.
allText = txtFile.responseText;
domore(allText,donePelicula);
}
}
}
txtFile.send(null);
}

how to execute second method only after first method is executed

I want to print a heading tag only after a paragraph tag is loaded. Below is my Javascript code. See the plunker for more clarification: http://embed.plnkr.co/aheHkSQUBft5A4Z3wkie/preview
function changeText(cont1, cont2, speed){
var Otext = cont1.text();
var Ocontent = Otext.split("");
var i = 0;
function show() {
if (i < Ocontent.length) {
cont2.append(Ocontent[i]);
i = i + 1;
};
};
var Otimer = setInterval(show, speed);
};
$(document).ready(function() {
changeText($("p"), $(".p2"), 30);
clearInterval(Otimer);
});
$(document).ready(function() {
changeText($("h2"), $(".h2"), 30);
clearInterval(Otimer);
});
I would do something like this (please not that ES6 Promises aren't supported by Internet Explorer, but there are shims to use Promises with old browsers too).
You'll have to fill out the parts commented to get it to work though:
var Otimer;
/*#TODO: refactor show() function to use ES6 Promises (eventually with shims) */
function show(Ocontent) {
var i = 0;
if (i < Ocontent.length) {
cont2.append(Ocontent[i]);
i = i + 1;
};
if (Otimer === undefined) {
Otimer = setInterval(show, speed); // Remember to fulfill the promise and remove the interval once it's finished
}
// return the promise
};
function changeText(p1, p2, speed) {
var Otext = p1.text();
var Ocontent = Otext.split("");
return show(Ocontent);
};
$(function () {
changeText($("p"), $(".p2"), 30).then(function() { // We call changeText the second time after the promise return by changeText() is fulfilled and the show() function has finished
Otimer = undefined;
changeText($("h2"), $(".h2"), 30);
});
});
first of all, variable declaring inside of function is scoped variable, which You cannot access from outside of the function.
so the line clearInterval(Otimer); never works.
the code below is fixed code of the scope issue and using callback to implement what you want.
function changeText(cont1, cont2, speed, cb) {
var Otext = cont1.text();
var Ocontent = Otext.split("");
var i = 0;
function show() {
if (i < Ocontent.length) {
cont2.append(Ocontent[i]);
i++;
}else{
clearInterval(Otimer)
if(cb) cb()
}
};
var Otimer = setInterval(show, speed);
};
$(document).ready(function() {
changeText($("p"), $(".p2"), 30, function(){
changeText($("h2"), $(".h2"), 30);
});
});
http://plnkr.co/edit/xowItFUWqI79obi4ZVNV?p=preview

jQuery not responding to timed events

Im having trouble getting my second function to react to the changes the first function brings.
var jumbotron = function(){
var jumbotronCounter = 1
var jumbotronSwitch = function(){
var jumbotronTimer = function(){
jumbotronCounter++
}
jumbotronTimer();
if (jumbotronCounter > 3){
jumbotronCounter = 1
}
console.log(jumbotronCounter);
}
setInterval(jumbotronSwitch,7000);
var jumbotronListener = function(){
if(jumbotronCounter = 1){
console.log('first');
}else if(jumbotronCounter = 2){
console.log('second');
}else if(jumbotronCounter = 3){
console.log('third');
}
};
jumbotronListener();
}
jumbotron();
Id like to use "jumbotronListener" to run some code when "jumbotronCounter" changes
jumbotronListener is indeed only running once. You can, instead, run it every time the interval runs:
var jumbotron = function () {
var jumbotronCounter = 1;
var jumbotronSwitch = function () {
var jumbotronTimer = function () {
jumbotronCounter++;
};
jumbotronTimer();
if (jumbotronCounter > 3) {
jumbotronCounter = 1;
}
// Execute the listener every time the interval runs
jumbotronListener();
console.log(jumbotronCounter);
};
setInterval(jumbotronSwitch, 7000);
// Run for the first time if you wish:
jumbotronListener();
// Set this as function so you can 'use it before declaring it'
function jumbotronListener() {
// You had invalid operators. = assigns and === compares (strictly)
if(jumbotronCounter === 1) {
console.log('first');
} else if(jumbotronCounter === 2) {
console.log('second');
} else if(jumbotronCounter === 3) {
console.log('third');
}
}
};
jumbotron();
You also had some missing semicolons in there, sometimes it's not a problem since JavaScript auto-inserts them, but sometimes it is, so it's a good idea to always make sure to manually insert them where they go.

unbind/turn off a function in jquery

Good day all, I'm trying to make a jquery game where a group of enemy will spawn after a group of enemy gets destroyed. I'm calling alien_cruiser() function & unbinding minion_roulette() function after minion_roulette_counter gets 0. But every time I run, function does not get unbind & after counter gets 0 both type of enemies show. I want to run them one by one. Here are the codes:
var sound = new Audio("sounds//dishoom.ogg");
var score = 0;
var minion_roulette_life = 10;
var cruiser_life = 20;
var minion_roulette_counter = 3;
var cruiser_counter = 3;
function processBullet() {
$(".projectile").each(function() {
var maxTop = $(this).offset().top;
var breakable1 = $(this).collision("#minion-roulette");
var breakable2 = $(this).collision("#cruiser");
$(this).css("top", maxTop - 25);
if (breakable1.length != 0 || breakable2.length != 0) {
$(this).remove();
}
if (maxTop <= 35) {
$(this).remove();
}
if (breakable1.length != 0) {
--minion_roulette_life;
if (minion_roulette_life == 0) {
sound.play();
breakable1.remove();
minion_roulette(true);
minion_roulette_counter--;
$("#score").html(++score);
minion_roulette_life = 10;
}
}
//This is the place where it checks if counter is 0 or not
if (minion_roulette_counter == 0) {
$('#content').unbind(function() {
minion_roulette(false)
});
alien_cruiser(false);
minion_roulette_counter = -1;
}
if (breakable2.length != 0) {
--cruiser_life;
if (cruiser_life == 0) {
sound.play();
breakable2.remove();
alien_cruiser(true);
$("#score").html(++score);
cruiser_life = 20;
}
}
});
}
Am I doing any wrong here? Please I need a solution badly. Tnx.
In this situation, you could use a conditional statement to determine which function to call.
For example:
if (minion_roulette_counter == 0) {
alien_cruiser();
}
else {
minion_roulette();
}
Binding and unbinding doesn't 'turn off' a function, unfortunately. To quote MDN:
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
– MDN: 'Bind'

Javascript: Check if function is TRUE

i have a function, which should return TRUE, when IF condition inside FOR cyklus is met. (i tested that condition, it works)
createBtn.addEventListener('click',function (e){
var ch = function check(){
var url = "http://hotel.010.sk/skyfit/read.php";
var json, poc, vypis;
var i=0;
var xhr = Ti.Network.createHTTPClient({
onload: function() {
json = JSON.parse(this.responseText);
for (i = 0; i < json.poc.length; i++) {
prnt = json.poc[i];
if(win.xtra_id == prnt.id_cv && picker.getSelectedRow(0).title == prnt.datum && prnt.capacity <= prnt.cnt ){
return true;
}
};
}
});
xhr.open("GET", url);
xhr.send();
};
...
But when i call function here to check it turns me always true, unless IF condition in check() is not met!
if(ch){
alert('Something');
}
How to fix my function to get TRUE only when my condition is met?
Thanks.
This expression
if (ch) {
is always true, because ch is a function and ToBoolean(function) === true.
However even if you changed it to if (ch()) {..} it would not work anyway, because inside of the function you perform asynchronous operation. Function just returns without waiting for it to finish. In this case you should use callbacks or promise patters. Simplest is callback.
var ch = function check(callback) {
// ...
var xhr = Ti.Network.createHTTPClient({
onload: function () {
json = JSON.parse(this.responseText);
var status = false;
for (i = 0; i < json.poc.length; i++) {
prnt = json.poc[i];
if (win.xtra_id == prnt.id_cv && picker.getSelectedRow(0).title == prnt.datum && prnt.capacity <= prnt.cnt) {
status = true;
}
};
callback(status);
}
});
// ...
};
ch(function(status) {
if (status) {
alert('Something')
}
});
Please try with following thing to check condition should always true
while(true){
alert('something');
}
Your function, ch has no return value! It launches the Ti.Network.createHTTPClient function where you define an anonymous callback function (onload: function(){...). That anonymous function is executed after the ch has already returned. You'll need to either check your conditional after the callback:
...
if (win.xtra_id == prnt.id_cv && picker.getSelectedRow(0).title == prnt.datum && prnt.capacity <= prnt.cnt) {
alert('something') //DO YOUR STUFF HERE!
return true;
}
...
or wait for the callback to happen before you check the conditional using some global flags:
var MYFLAG=-1
...
if (win.xtra_id == prnt.id_cv && picker.getSelectedRow(0).title == prnt.datum && prnt.capacity <= prnt.cnt) {
MYFLAG=1
return true;
}
else
{
MYFLAG=0
}
...
//use a timer to check the flag every 500ms
var myInterval = setInterval(function()
{
if (MYFLAG != -1) {
if (MYFLAG==1) {
alert('returned true :)');
}
else {
alert('did not return true :(');
}
clearInterval(myInterval);
}
}, 500);

Categories

Resources