how to use setTimeout or setInterval properly - javascript

I am using google maps and i am trying to put a pause in execution to prevent QUERY_LIMIT usage issue. My function that plots the addresses looks like this.
The code works, however i want to try setTimeout or setInterval to see if its going to look better on UI.
How do i call it, what should be the first argument?
Thanx alot.
vLocations = [];
for (var i = 0; i < vAddresses.length; i++) {
//pause to prevent OVER_QUERY_LIMIT issue
//geocode "free" usage limit is 5 requests per second
//setTimeout(PlotAddressesAsUnAssigned, 1000);
//sleep(500);
//this will resolve the address and store it in vLocations
AddWaypointAndUnassigned(vAddresses[i]);
var z = i % 4;
if (z==0 && i != 0) {
//sleep after every 5th geocode call
//alert('going to sleep...i: ' + i);
//sleep(3000);
}
}

Doing a pause (asynchronous execution) inside a loop (synchronous) will usually result in a lot of trouble.
You can use recursive calls that are done only when a timeout ends.
var vLocations = [];
// Manages the timeout and recursive calls
function AddWaypointAndUnassignedWithPause(index){
setTimeout(function(){
// When the timeout expires, we process the data, and start the next timeout
AddWaypointAndUnassigned(vAddresses[index]);
// Some other code you want to execute
var z = i % 4;
if (z==0 && i != 0) {
//sleep after every 5th geocode call
//alert('going to sleep...i: ' + i);
//sleep(3000);
}
if(index < vAddresses.length-1)
AddWaypointAndUnassignedWithPause(++index);
}, 1000);
}
// Start the loop
AddWaypointAndUnassignedWithPause(0);
JSFiddle example.

Try this, hope this will help
vLocations = [];
for (var i = 0; i < vAddresses.length; i++) {
//pause to prevent OVER_QUERY_LIMIT issue
setTimeout(function(){
//this will resolve the address and store it in vLocations
AddWaypointAndUnassigned(vAddresses[i]);
}, 500);
var z = i % 4;
if (z==0 && i != 0) {
//sleep after every 5th geocode call
//alert('going to sleep...i: ' + i);
//sleep(3000);
}
}

What about a waiting line, thats fired when an item is added and stopped when there are no items left.
With setTimeout:
var INTERVAL = 1000 / 5;
var to = null;
var vLocations = [];
function addAddress(vAddress) {
vLocations.push(vAddress);
startTimeout();
}
function startTimeout() {
if( to === null ) {
to = setTimout(processLocation, INTERVAL);
}
}
function processLocation() {
if( vLocations.length ) {
var vAddress = vLocations.shift();
AddWaypointAndUnassigned(vAddress);
to = setTimout(processLocation, INTERVAL);
} else {
to = null;
}
}
With setInterval:
var INTERVAL = 1000 / 5;
var to = null;
var vLocations = [];
function addAddress(vAddress) {
vLocations.push(vAddress);
startInterval();
}
function startInterval() {
if( to === null ) {
to = setInterval(processLocation, INTERVAL);
}
}
function processLocation(cb) {
if( vLocations.length ) {
var vAddress = vLocations.shift();
AddWaypointAndUnassigned(vAddress);
} else
clearInterval(to);
to = null;
}
}

Related

Javascript Memory

I was wondering why my program crashes after its made its first match....any ideas would be greatly appreciated. Below is the code snippet. Thanks for the input!
var clicks = 0; //counts how may picks have been made in each turn
var firstchoice; //stores index of first card selected
var secondchoice; //stores index of second card selected
var match = 0; //counts matches made
var backcard = "deck.jpg"; //shows back of card when turned over
var faces = []; //array to store card images
faces[0] = 'pic1.jpg';
faces[1] = 'pic2.jpg';
faces[2] = 'pic3.jpg';
faces[3] = 'pic3.jpg';
faces[4] = 'pic2.jpg';
faces[5] = 'pic1.jpg';
function choose(card) {
if (clicks === 2) {
return;
}
if (clicks === 0) {
firstchoice = card;
document.images[card].src = faces[card];
clicks = 1;
} else {
clicks = 2;
secondchoice = card;
document.images[card].src = faces[card];
timer = setInterval("check()", 1000);
}
}
/* Check to see if a match is made */
function check() {
clearInterval(timer); //stop timer
if (faces[secondchoice] === faces[firstchoice]) {
match++;
document.getElementById("matches").innerHTML = match;
} else {
document.images[firstchoice].src = backcard;
document.images[secondchoice].src = backcard;
clicks = 0;
return;
}
}
The first parameter of setInterval needs to be a function not a string pretending to be a function. So you would want this:
timer = setInterval(function() { check(); }, 1000);
Of course, you can simplify:
timer = setInterval(check, 1000);
Not sure why you're using setInterval() here. You could more easily just do:
timer = setTimeout(check, 1000);
The advantage is there is no interval to clear in the check() function.
The other issue is that you are not resetting your 'clicks' counter to 0 when there is a match.
You want this:
function check() {
clearInterval(timer); //stop timer
if (faces[secondchoice] === faces[firstchoice]) {
match++;
document.getElementById("matches").innerHTML = match;
} else {
document.images[firstchoice].src = backcard;
document.images[secondchoice].src = backcard;
}
clicks = 0;
}
I think you have to declare you timer function globally. Its only defined in the scope of the first function, so in the second when you try to clear it nothing happens:
var timer = ''; //Declare timer up here first!
function choose(card) { ... }
function check() { ... }

setTimeout executing is not stopping further iterations from occurring - need other solution

I am making a typing game using just jQuery and javascript. It worked fine as a single player game, feel free to play it at http://typetothestars.bitballoon.com/ However, I am planning to keep ratcheting up its complexity level. So I am trying to add muti player to it now.
here it is in jsfiddle minus images https://jsfiddle.net/u32s4yty/
My problem lies in my runRace functions. I was expecting the race to run for player 1, when the interval ended, it would then start again for player 2. Instead, it runs through all the iterations right away. So apperently setTimeout is not going to work here.
Any suggestions as to how to make it work?
Thanks!
// ** RUNNING GAME FUNCTIONS ** \\
//hides instructions and reveals game
function setupRace(i) {
console.log("In Race Setup")
$("#word").show();
document.getElementById("word").focus();
generateWords();
$(".toType").text(gameWords[0]);
$("#instructions").hide();
$(".wordDisplay").show();
$(".player").show();
var playerAvatar = 'url("images/' + playerInfo[i].avatar + '.png")'
$(".player").css({background: playerAvatar});
}
//game timer - IS NOT STOPPING THE OTHER FUNCTIONS FROM RUNNING
var timeoutID;
function timer(i) {
timeoutID = window.setTimeout(checkEndRace, 3000, i)
console.log("i = " + i);
console.log(playerInfo[i]);
}
function checkEndRace(i) {
console.log("in check end race - num players " + numPlayers);
if (i < numPlayers - 1) {
setupRace(i);
}else {
endRace(i);
}
}
//advances ship on correct typing
function runRace() {
console.log("In run race");
var i = 0;
while (i < playerInfo.length) {
console.log("in run race loop");
setupRace(i);
timer(i);
//timer is skipping ahead to the next iteration, eventhough
//checkEndRace hasn't run yet
var j = 1;
$(document).keyup(function(e){
var targetWord = $(".toType").text();
var typedWord = $("#word").val();
while (j < gameWords.length){
if(typedWord === targetWord){
$(".player").css({left: "+=15px",});
targetWord = $(".toType").text(gameWords[j]);
$("#word").val("");
j++;
}else {
return
};
}
});
i ++;
};
}
I was hoping to use setTimeout to stop all functions the following functions, until the interval is completed.
Calls to setTimeout return immediately and only execute once so one easy/common way to handle ordering them is to make tail calls (tick) to setTimeout and to put all requests in a queue.
// ** RUNNING GAME FUNCTIONS ** \\
var raceHandlers = [];
var raceTimout = 3000;
function tick() {
// Tail call
if (raceHandlers.length > 0) {
var action = raceHandlers.pop();
setTimeout(action[0],raceTimeout,action[1]);
}
}
//hides instructions and reveals game
function setupRace(i) {
console.log("In Race Setup")
$("#word").show();
document.getElementById("word").focus();
generateWords();
$(".toType").text(gameWords[0]);
$("#instructions").hide();
$(".wordDisplay").show();
$(".player").show();
var playerAvatar = 'url("images/' + playerInfo[i].avatar + '.png")'
$(".player").css({background: playerAvatar});
tick();
}
//advances ship on correct typing
function runRace() {
console.log("In run race");
var i = 0;
while (i < playerInfo.length) {
console.log("in run race loop");
//setupRace(i);
raceHandlers.unshift([setupRace,i]);
//timer is skipping ahead to the next iteration, eventhough
//checkEndRace hasn't run yet
var j = 1;
$(document).keyup(function(e){
var targetWord = $(".toType").text();
var typedWord = $("#word").val();
while (j < gameWords.length){
if(typedWord === targetWord){
$(".player").css({left: "+=15px",});
targetWord = $(".toType").text(gameWords[j]);
$("#word").val("");
j++;
}else {
return
};
}
});
i ++;
};
raceHandlers.unshift([endRace,playerInfo.length]);
tick();
}

Delay inside for loop not working

I want to make a delay inside my for loop, but it won't really work.
I've already tried my ways that are on stackoverflow, but just none of them work for what I want.
This is what I've got right now:
var iframeTimeout;
var _length = $scope.iframes.src.length;
for (var i = 0; i < _length; i++) {
// create a closure to preserve the value of "i"
(function (i) {
$scope.iframeVideo = false;
$scope.iframes.current = $scope.iframes.src[i];
$timeout(function () {
if ((i + 1) == $scope.iframes.src.length) {
$interval.cancel(iframeInterval);
/*Change to the right animation class*/
$rootScope.classess = {
pageClass: 'nextSlide'
}
currentId++;
/*More information about resetLoop at the function itself*/
resetLoop();
} else {
i++;
$scope.iframes.current = $scope.iframes.src[i];
}
}, $scope.iframes.durationValue[i]);
}(i));
}
alert("done");
This is what I want:
First of all I got an object that holds src, duration and durationValue.
I want to play both video's that I have in my object.
I check how many video's I've got
I make iframeVideo visible (ngHide)
I insert the right <iframe> tag into my div container
It starts the $timeout with the right duration value
If that's done, do the same if there is another video. When it was the last video it should fire some code.
I hope it's all clear.
I've also tried this:
var iframeInterval;
var i = 0;
$scope.iframeVideo = false;
$scope.iframes.current = $scope.iframes.src[i];
iframeInterval = $interval(function () {
if ((i + 1) == $scope.iframes.src.length) {
$interval.cancel(iframeInterval);
/*Change to the right animation class*/
$rootScope.classess = {
pageClass: 'nextSlide'
}
currentId++;
/*More information about resetLoop at the function itself*/
resetLoop();
} else {
i++;
$scope.iframes.current = $scope.iframes.src[i];
}
}, $scope.iframes.durationValue[i])
Each $timeout returns a different promise. To properly cancel them, you need to save everyone of them.
This example schedules several subsequent actions starting at time zero.
var vm = $scope;
vm.playList = []
vm.playList.push({name:"video1", duration:1200});
vm.playList.push({name:"video2", duration:1300});
vm.playList.push({name:"video3", duration:1400});
vm.playList.push({name:"video4", duration:1500});
vm.watchingList=[];
var timeoutPromiseList = [];
vm.isPlaying = false;
vm.start = function() {
console.log("start");
//ignore if already playing
if (vm.isPlaying) return;
//otherwise
vm.isPlaying = true;
var time = 0;
for (var i = 0; i < vm.playList.length; i++) {
//IIFE closure
(function (i,time) {
console.log(time);
var item = vm.playList[i];
var p = $timeout(function(){playItem(item)}, time);
//push each promise to list
timeoutPromiseList.push(p);
})(i,time);
time += vm.playList[i].duration;
}
console.log(time);
var lastPromise = $timeout(function(){vm.stop()}, time);
//push last promise
timeoutPromiseList.push(lastPromise);
};
Then to stop, cancel all of the $timeout promises.
vm.stop = function() {
console.log("stop");
for (i=0; i<timeoutPromiseList.length; i++) {
$timeout.cancel(timeoutPromiseList[i]);
}
timeoutPromiseList = [];
vm.isPlaying = false;
};
The DEMO on PLNKR.
$timeout returns promise. You can built a recursive chain of promises like this, so every next video will play after a small amount of time.

Javascript - countdown timer is incrementing not persecond

Can anyone tell me what am i doing wrong? i have the timer which is displaying with 2 or 3 or 4 seconds at once increment instead of per second.
var call_s = 0;
var call_m = 0;
var call_h = 0;
var call_connected = null;
var display = null ;
function connected_timer_start(tototo) {
call_connected = setTimeout(function() {
call_s++;
if (call_s>59) {
call_s = 0;
call_m++;
}
if (call_m>59){
call_m = 0;
call_h++;
}
display = (call_h < 10 ? '0' : '') + call_h + ':' +
(call_m < 10 ? '0' : '') + call_m + ':' +
(call_s < 10 ? '0' : '') + call_s;
console.log(display);
connected_timer_start();
}, 1000);
}
function connected_timer_stop() {
call_s = 0;
call_m = 0;
call_h = 0;
clearTimeout(call_connected);
call_connected = null;
document.getElementById('display').style.display = 'none';
}
As jfriend00 said, you shouldn't use setTimeout() to figure out the time values, because it's not reliable. A version of code that uses Date() is actually shorter and simpler:
var begining_timestamp = null;
var call_connected = null;
var call_ms = null;
var display = null ;
function connected_timer_start() {
if (call_connected==null) {
begining_timestamp = (new Date()).getTime();
count();
} else {
console.log('One timer is already started!');
}
}
function count() {
call_connected = setTimeout(function() {
getCallLength();
count();
}, 1000);
}
function getCallLength() {
call_ms = (new Date()).getTime() - begining_timestamp;
var tmp_date = new Date(null);
tmp_date.setSeconds(call_ms/1000);
display = tmp_date.toISOString().substr(11, 8);
console.log(display);
}
function connected_timer_stop() {
clearTimeout(call_connected);
getCallLength();
call_connected = null;
document.getElementById('display').style.display = 'none';
}
I see several advantages to this approach:
times are accurate even if setTimeout triggers every 2 seconds or at random times, your call duration will be accurate
the call duration gets updated when the call ends, to make sure it's completely accurate
you have the call time down to milliseconds, if you ever need that
the call_ms variable does not get cleared when a call ends, but when a call starts; that means between two calls, you can always have the last call length expressed in milliseconds
as AlexAtNet suggested, you may start the timer more than once, by mistake; so connected_timer_start now checks if the timer is not already started

Sequencing consecutive functions and adjust for-loop in javascript/jquery

Background: the code below picks either a word or an image and displays it in my 'abc' div. It measures the reaction time.
Aim: I want to have the function run only 8 times (not 8 keypresses), record the time for each run regardless the keypress event (i.e. a time of 2000 when no key is pressed), and I want this function run first, and after it has finished I want to run a second function.
I researched the $deferred method and seem to have failed to adopt it. Furthermore, my 8 function runs, are not eight at all, but seem more like 8 simultaneous runs.
So basically I want to run my function 8 times, then run a next function, and record the time from appearance of a stimulus to the next if not interrupted by keypress.
I'm stuck with it for some time now and have probably lost the overview.
var reac_arr = [];
var t1;
function firstFunction(){
var def = $.Deferred();
for (var i = 1; i <= 8; i++) {
$(function cit(){
var timeout = 0;
function showNext(){
t1 = (new Date()).getTime();
if (Math.random() < 0.5) {
var new_word = stim.name;
$("#abc").text(new_word);
}
else {
var new_img = stim.path;
$("#abc").empty();
var prox_img = $('<img id="abcimg">');
prox_img.attr('src', new_img);
prox_img.appendTo('#abc');
}
timeout = setTimeout(function(){
showNext()
}, 2000);
}
$(document).keypress(function(e){
if ($(e.target).is('input, textarea')) {
return;
};
clearTimeout(timeout);
if (e.which === 97 || e.which === 108 || e.which === 32) {
setTimeout(function(){
showNext();
}, 300);
var t2 = (new Date()).getTime();
var reac_time = t2 - t1;
reac_arr.push(reac_time);
}
});
});
};
setTimeout(function() {
def.resolve();
}, 1000);
return def.promise();
}
function secondFunction(){
var def = $.Deferred();
alert("It works!")
};
setTimeout(function() {
def.resolve();
}, 1000);
return def.promise();
}
firstFunction().pipe(secondFunction);
Your code seems a bit bloated but if I understood correctly all you need is setInterval().
var counter = 0;
var ticker = setInterval(myFunction,2000);//Setup a function to run every 2000ms
function myFunction()
{
//do your thing
counter++;//
if(counter==8){
//on the 8th time run next function...
}
}
$(document).keypress(function(e){
clearInterval(ticker);//Stop the ticker on keypress
});

Categories