setInterval doesn't get cleared, function keeps getting executed - javascript

I have the following function:
function monitorClimate() {
var sensorReadingInterval;
function startClimateMonitoring(interval) {
sensorReadingInterval = setInterval(function() {
io.emit('sensorReading', {
temperature: sensor.getTemp() + 'C',
humidity: sensor.getHumidity() + '%'
});
}, interval);
console.log('Climate control started!');
}
function stopClimateMonitoring() {
clearInterval(sensorReadingInterval);
console.log('Climate control stopped!');
}
return {
start: startClimateMonitoring,
stop: stopClimateMonitoring
};
}
I am watching a button for changes of state like this:
button.watch(function(err, value) {
led.writeSync(value);
if (value == 1) {
monitorClimate().start(1000);
} else {
monitorClimate().stop();
}
});
The problem is that even after the monitorClimate().stop() call, setInterval keeps getting triggered, thus SocketIO keeps on emitting the sensorReading event.
What am I doing wrong here?

Every time you call monitorClimate() you are creating a new set of functions so monitorClimate().start() and monitorClimate().stop() are not working on the same interval. Try something like:
var monitor = monitorClimate();
button.watch(function(err, value) {
led.writeSync(value);
if (value == 1) {
monitor.start(1000);
} else {
monitor.stop();
}
});

Related

Vuejs - On input, run a function (but with a delay)

I have an input field, and v-on:input it runs a method called activate that looks like this:
export default: {
data() {
return {
isHidden: true
}
},
methods: {
activate() {
this.isHidden = false;
}
}
}
isHidden turns on/off some icon (it doesn't really matter what this data property is; I'm just using it for example purposes).
So currently, when a user does an input it immediately turns on the activate function. Is there a way to, perhaps, put it on a delay via setTimeout? I've tried doing the following but it doesn't work:
methods: {
setTimeout(function() {
activate() {
this.isHidden = false;
}
}, 500)
}
Try this:
methods: {
activate() {
setTimeout(() => this.isHidden = false, 500);
}
}
Or without arrow function:
methods: {
activate() {
var that = this;
setTimeout(function() { that.isHidden = false; }, 500);
}
}
First, set a var in your data:
data() {
return {
typing: Date.now()
}
}
then in your methods, create a function that will fire on keyup:
pendingSave(val){
let saving = setTimeout(() => {
this.saveItem(val) // method to call when user is done typing
},1203)
if(val){
saving
if(Date.now() - this.typing < 1200) clearTimeout(saving)
this.typing = Date.now();
}
}
In your HTML, you would have something like this:
<input v-model="title" v-on:keyup="pendingSave(title)" type="text" placeholder="Title" />
What happens is that when the user clicks inside the input, and types a character, it will call 'pendingSave()'. This will get the function ready to call via setTimeout() in 1203ms. If the user types another character, and the time is 'less' than 1200ms, it will cancel setTimeout()... otherwise it will fire the function saveItem() as intended.

CasperJS: WaitFor timeout function to do rescroll?

I met some problem when I use CasperJS to scrape a website. The website is dynamically loaded like Twitter, so I want to do infinite scroll,
and thanks to #Artjom B. I found you code to do this.
var tryAndScroll = function (casper) {
try {
casper.echo('SCROLL!!');
casper.scrollToBottom();
if (casper.exists('div.loading')) {
var curItems = casper.evaluate(getCurrentInfosNum);
casper.echo(curItems);
casper.waitFor(function check() {
return curItems != casper.evaluate(getCurrentInfosNum);
}, function then() {
casper.wait(800);
tryAndScroll(casper);
}, function onTimeout() {
casper.emit('scroll.timeout',curItems);
}, 15000);
} else {
casper.echo("No more items");
return true;
}
} catch (err) {
casper.echo(err);
}
} //casper.tryAndScroll
And now, I want to continue to scroll many times when the timeout function invoked so I create my own event listener,‘scroll.timeout’.
var SRCOLL_NUM = 0;
var PreOfLoaded = 0;
casper.on('scroll.timeout', function (NumOfLoaded) {
if (SRCOLL_NUM <= 4) {
if (PreOfLoaded == NumOfLoaded)
SRCOLL_NUM++;
this.echo("Scroll Timeout,reScroll");
PreOfLoaded = NumOfLoaded;
tryAndScroll(casper);
} else {
this.echo("Scroll Timeout,reScroll times maximum");
SRCOLL_NUM = 0;
PreOfLoaded = 0;
}
});
However, when scroll timeout occurred, it printed Scroll Timeout,reScroll on the console. Then it skips tryAndScroll() and go to the next step in the main function. I want to continue to next step after retry scroll many times. What should I do?
I found CasperJS author illustrate :Automatic retry when open fails
var casper = require('casper').create();
casper.tryOpen = function(url, then) {
return this.then(function() {
this.open(url);
this.waitFor(function testStatus() {
return this.getCurrentHTTPStatus === 200;
}, then, function onFail() {
console.log('failed, retrying');
this.tryOpen(url);
}, 2000);
});
};
casper.start().tryOpen('http://failing.url.com/foo.bar', function() {
this.echo('wow, it worked, wtf');
}).run();
unfortunately, it doesn't work for me.
Try this
return this.currentHTTPStatus === 200;
I tested with the newest version of casperjs 1.1.1, it's working fine

Need help stopping slideshow using jQuery

I've run into an issue with jQuery code that I'd like some help on. While the next and previous buttons work correctly, there appears to be an issue correctly stopping a slideshow. This is probably something we're completely overlooking, but I can't see what.
There is no JavaScript errors showing in the console. The interrupt method was being reached - at one point I had console.log calls in there to verify (cleaned up for presentation reasons).
http://jsfiddle.net/eLn83ep0/
Your help is much appreciated.
The below code is the functionality for prev/stop/start/next:
if ($(settings.next).size()) {
$(settings.next).bind('click.scrollface', function (e) {
methods.interrupt.call($this);
methods.next.call($this);
});
}
if ($(settings.pause).size()) {
$(settings.pause).bind('click.scrollface', function (e) {
methods.interrupt.call($this);
});
}
if ($(settings.play).size()) {
$(settings.play).bind('click.scrollface', function (e) {
methods.interrupt.call($this);
methods.start.call($this);
});
}
/*
* Setup up prev bindings
*/
if ($(settings.prev).size()) {
$(settings.prev).bind('click.scrollface', function (e) {
methods.interrupt.call($this);
methods.prev.call($this);
});
}
Here is the method for interrupt:
interrupt: function (time) {
return $(this).each(function () {
var data = $(this).data('scrollface');
console.log(data);
console.log('...');
if (!data) {
return false;
}
var $this = $(this),
period = 0;
/*
* Stop the timer, and wait a period of time before restarting it.
* Period defaults to the timer interval
*/
if (data.timer) {
if (typeof time !== "number") {
period = data.interval;
} else {
period = time;
}
methods.stop.call(this);
setTimeout(function resume_timer () {
clearInterval(data.timer);
data.timer = null;
methods.start.call($this);
}, period);
}
});
},
if ($(settings.pause).size()) {
$(settings.pause).bind('click.scrollface', function (e)
methods.stop.call($this);
});
}
if ($(settings.play).size()) {
$(settings.play).bind('click.scrollface', function (e) {
methods.start.call($this);
});
}
and delete the interrupt call in prev and next
//methods.interrupt.call(this);
because the interrupt method stopping the interval method and after timeout starting again, so most time you pause in this timeout but after this timeout the interrupt method starting the intervall again and dont care if you stoped it manually
see your updated fiddle working here http://jsfiddle.net/7ko4rdda/
Edit:
if you call interrupt with 0 for the buttons prev next click handler then you have the expected behavier that the period for the intervall starts new after next/prev click
if ($(settings.prev).size()) {
$(settings.prev).bind('click.scrollface', function (e) {
methods.interrupt.call($this,0);
methods.prev.call($this);
});
}
if ($(settings.next).size()) {
$(settings.next).bind('click.scrollface', function (e) {
methods.interrupt.call($this,0);
methods.next.call($this);
});
}
http://jsfiddle.net/7ko4rdda/1/

Prevent recursive function locking the browser

I have a recursive function which is locking my browser while running.
While this function is running all my jquery commands are locked waiting for the function end.
What should I do to make this function asynchronous?
This function runs on document.ready
function SearchTrip() {
$.post("/extensions/searchtrip", {
from: $("#from").val(),
to: $("#to").val(),
ddate: $("#ddate").val()
},
function (mReturn) {
if (mReturn.fTotalAmount != '0,00') {
var sAirline = '';
if (mReturn.Airline)
sAirline = ' pela ' + mReturn.Airline;
$("#buscandoPassagens").hide();
} else if (SearchTripAmount < 5) {
SearchTripAmount++;
setTimeout(function () {
SearchTrip();
}, 500);
} else {
$("#pNaoEncontrada").show();
}
},
"json");
}
If you want to run it asynchronously just wrap everything with setTimeout:
function SearchTrip(){
setTimeout( function() {
//this is your $.post i just deleted 'content' to make answer easier to read
$.post();
}, 0);
}

Why doesn't the clearInterval() works?

I'm new to JavaScript and I'm having problems with this script.
it's part of a web game and the script is suppose to refresh the page until the player wins or loses.
for some reason it doesn't stop refreshing, I put an alert function to check if the functions works, and i get the alerts but it's still continue refreshing the page.
what am i doing wrong?
var t;
$(document).ready(function () {
intervals();
});
function intervals() {
t = self.setInterval('refreshData()', 10000);
}
function youWin() {
var f = $('#status:contains("YOU ARE THE WINNER!")');
if (f.length > 0) {
alert("YOU ARE THE WINNER!");
t = clearInterval(t);
}
}
function youlose() {
var f = $('#status:contains("You lost!")');
if (f.length > 0) {
alert("You lost!");
t = clearInterval(t);
}
}
function refreshData() {
$('#ajaxGame').load('RefreshCurrentPlayerServlet #ajaxGame');
youWin();
youlose();
}
You need to fix the reference to self and fix the .load() call.
.load() is asynchronous so it does not complete before you call youWin() and youLose() right after it. You need a completion function so you can check winning or losing after the .load() completes successfully.
refreshData() should be structured like this:
function refreshData() {
$('#ajaxGame').load('RefreshCurrentPlayerServlet #ajaxGame', function() {
youWin();
youlose();
});
}
You also should change this:
t= self.setInterval('refreshData()',10000);
to this:
t = window.setInterval(refreshData, 10000);
I don't see that self was even defined so that could have also been causing your problem and you should use the function reference directly rather than put in a string.
And, as a cleanup issue, you should change both occurences of this:
t = clearInterval(t);
to this:
clearInterval(t);
Here's a cleaned up version of the code that also eliminates global variables and unnecessary function definitions:
$(document).ready(function() {
var t = window.setInterval(function() {
$('#ajaxGame').load('RefreshCurrentPlayerServlet #ajaxGame', function() {
youWin();
youlose();
});
}, 10000);
function youWin() {
if ($('#status:contains("YOU ARE THE WINNER!")').length) {
alert("YOU ARE THE WINNER!");
clearInterval(t);
}
}
function youlose() {
if ($('#status:contains("You lost!")').length) {
alert("You lost!");
clearInterval(t);
}
}
});

Categories

Resources