setInterval triggering faster than set - javascript

I am trying to build a dinosaur running game in React much like google chrome's.
My idea is that I will run a function at the exact moment the object is suppose to hit the dinosaur, around 3 seconds
function check4Death() {
if (playerClass !== '') {
console.log('safe')
}
else {
console.log('nope')
clearInterval()
}
}
setInterval(check4Death, 3000)
This function checks to see if the player is currently in the air
As my method of jumping is adding and then removing a class from my playerClass object
function Jump() {
setPlayerClass('jump')
setTimeout(() => {
setPlayerClass('')
}, 500);
}
Instead of the function telling me either safe or nope every three seconds, I get this
I am very confused as to why this is happening, I have a link to my full code here

Related

jQuery fadeIn() called repeatedly not working

This is a part of an JS-scanning function which runs about 3-5 times / sec.
Below is what I want to obtain .. but it (obviosly) does not work ... because it keeps "resetting" the fadeIn function 3-5 times every second.
if (scanResult) {
dosomething();
} else {
// Show error message
$("#error").fadeIn().delay(3000).fadeOut();
}
I could call a seperate function and/or checks with timestamps when it last was called.
But ... there must be a smarter jQuery-way?
Quick and dirty.
if (scanResult) {
dosomething();
} else {
// Show error message
if(!$("#error").hasClass("shown"))
$("#error").addClass("shown").fadeIn().delay(3000).fadeOut(() => {removeClass("shown");});
}

Not able to clear my setInterval in Ionic

I have an IONIC 4 application where I need to call an api every 20 seconds and if the user moves to other page need to stop calling that api. I am able to make the api call at every 20 seconds but not able to stop it when I move to some other page. Here is my code below, may I know where I went wrong?
rateTimer:any;
constructor(private loginServiceService: LoginServiceService) {
this.loginServiceService.getappData();
this.rateTimer=setInterval(() => {
this.loginServiceService.getappData();
}, 10000);
}
// When I move to other page, I clear the setInterval from here
ngOnDestroy() {
clearInterval(this.rateTimer);
}
As far as I know Ionic has a cache for page-navigation which is why ngOnDestroy/ngOnInit will not always work. However, there's ionViewDidLeave which should definitely fire, once the current page is moved away from (see https://ionicframework.com/docs/api/router-outlet#life-cycle-hooks for more details):
export class YourComponent {
ionViewDidLeave() {
// Do actions here
}
}

React Native background timer never stops

I'm building an app that has a timer to request geolocation while the timer is active. For a timer I'm using react-native-background-timer. Which is kind of working, but not exactly as I want.
With this piece of code:
BackgroundTimer.runBackgroundTimer(() => {
console.log('tic');
},
1000);
the timer is stopping when the app is in the background. While with this piece of code:
const intervalId = BackgroundTimer.setInterval(() => {
console.log('tic');
}, 1000);
it runs constantly even in the background, but I'm not able to stop it. When I run BackgroundTimer.clearInterval(intervalId);, the timer still runs. Even when I leave the screen and go back to my Home screen, the timer still ticks and never stops. This is not ideal, because I need timer to run for a few minutes and then stop.
I set the timer to 1 second to update time left on the screen. I was thinking about setting a timer once for 6 minutes, but then how do I update the state every second? Making 2 timers for this feels like a bad practise, even though it would work.
So to make it more clear, the user suppose to engage in certain activity like walking for a few minutes. So I can't let the timer to stop when user is answering a call or opened a music app to switch music or something else. Timer still needs to run and I need to measure the number of steps and distance with geolocation. It need to work flawlessly even if user opened another app, forgot about my app, and it would still run for the remaining time, then made a record to the database and stopped.
Try the following code snippet,
works both on android and ios
import { DeviceEventEmitter, NativeAppEventEmitter, Platform } from 'react-native';
import _BackgroundTimer from 'react-native-background-timer';
const EventEmitter = Platform.select({
ios: () => NativeAppEventEmitter,
android: () => DeviceEventEmitter,
})();
class BackgroundTimer {
static setInterval(callback, delay) {
_BackgroundTimer.start();
this.backgroundListener = EventEmitter.addListener("backgroundTimer", () => {
this.backgroundTimer = _BackgroundTimer.setInterval(callback, delay);
});
return this.backgroundListener;
}
static clearInterval(timer) {
if (timer) timer.remove();
if (this.backgroundTimer)
_BackgroundTimer.clearInterval(this.backgroundTimer);
_BackgroundTimer.stop();
}
}
export default BackgroundTimer;
Usage
const timer = BackgroundTimer.setInterval(callback, 1000);
BackgroundTimer.clearInterval(timer)
For some reason I got the following error when using #Aravind Vemula's answer.
When calling BackgroundTimer.clearInterval(timer); the following error appears:
timer.remove is not a function
That's why I modified the code slightly.
// parameter removed
static clearInterval() {
// ADD this if statement
if (this.backgroundListener){
this.backgroundListener.remove();
}
if (this.backgroundTimer)
_BackgroundTimer.clearInterval(this.backgroundTimer);
_BackgroundTimer.stop();
}
The above code checks if a backgroundlistener is registered. If yes it removes all listeners and especially our backgroundTimer.
Usage:
BackgroundTimer.clearInterval(); // removed parameter
After my change, everything is working fine on iOS 14.3.
#Aravind Vemula's answer working properly. But if user open the app from the background and timer code is added in background handler then when you stop the timer it is not working. So following changes you need to make in both the methods.
static setInterval(callback, delay) {
if (!this.backgroundListener && !this.locationTimer) {
_BackgroundTimer.start();
this.backgroundListener = EventEmitter.addListener('backgroundTimer', () => {
this.locationTimer = _BackgroundTimer.setInterval(callback, delay);
});
return this.locationTimer;
}
}
static clearInterval() {
if (this.backgroundListener) {
this.backgroundListener.remove();
}
if (this.locationTimer) {
_BackgroundTimer.clearInterval(this.locationTimer);
}
this.backgroundListener = false;
this.locationTimer = false;
_BackgroundTimer.stop();
_BackgroundTimer.start();
}

Why is the "webpage is slowing down" occuring on using a while loop with a setTimeout in React?

I made this component in React with a while loop which has a setTimeout inside it. It is causing the browser to stop responding and I get "webpage is slowing down" in Firefox developers browser and in chrome too. What is the possible reason? Here is the code:-
class Adbanner extends React.Component{
changer() {
var i=0;
while(i>=0 && i<4){
setTimeout(function(){
document.getElementById('ad').src=adarray[i];
i++;
}, 2000);
}
}
render() {
return (
<div>
<input id="ad" type="image" src={ad2} style={{position:'absolute',height:'50%',width:'100%'}}></input>
{setInterval(this.changer, 2000)}
</div>
);
}
}
export default Adbanner;
How to solve it?
var i=0;
while(i>=0 && i<4){
setTimeout(function(){
document.getElementById('ad').src=adarray[i];
i++;
}, 2000);
}
The setTimeout does not wait to be complete. setTimeout sends the function to a different data structure and keeps going through the code. It just keeps cycling repeatedly as fast as computationally possible. Try doing this:
var i=0;
while(i>=0 && i<4){
setTimeout(function(){
document.getElementById('ad').src=adarray[i];
i++;
}, 2000);
console.log('created a setTimeout')
}
It looks like you're trying to run the function 4 times, while waiting for 2000ms each run. setInterval with a clearInterval condition would be perfect for your needs
function changer() {
var i=0;
let imageChange = setInterval(() => {
if (i < 4) {
document.getElementById('ad').src=adarray[i];
i++
} else {
clearInterval(imageChange)
}
}, 2000)
}
You don't want to call setInterval inside your render function. Render is supposed to be free of side-effects. What is happening is that any time the component, or its parent changes, render is getting called. That means your interval is getting created possibly many times.
Instead, move the setInterval to componentDidMount()
Additionally, in your setInterval, you are creating 4 setTimeout calls. So, every 2 seconds, you will update the ad table 4 times. That doesn't seem to be exactly what your desire is.
There are few issues in this code-
document.getElementById is not a valid way to change attributes in React.
You are executing setInterval in render method. Now Imagine what's happening- the first time render is called setInterval is executed and then four setTimeout methods are being called. Upon the execution of first timeout render is getting called again which fires a new setInterval eventually. This is causing an infinite loop of setInterval and render.
You should use a commit phase lifecycle method for setinterval method like componentDidMount so that setInterval is called only once.
The while loops until i is iterated 4 times. Now, i is iterated when setTimeout executes the function given to it, BUT that function is only executed after 2 seconds. Meanwhile, while loops a zillion times.
You're not using the power of React, though! Check out this guide on the React website that teaches you how to do this exact scenario: https://reactjs.org/docs/state-and-lifecycle.html
e.g.
class Adbanner extends React.Component {
// Set this component's state as the current ad index
state = {ad: 0};
// Rotates the ad index state every 2 seconds
rotateAd () {
this.setState({ad: (this.state.ad + 1) % adarray.length});
this.timer = setTimeout(this.rotateAd, 2000);
}
// Start rotating the ad index when mounted
componentDidMount () {
this.rotateAd();
}
// Renders when constructed, then whenever the state changes (or when React wants to)
render() {
return (
<div>
<input id="ad" type="image" src={adarray[this.state.ad]} style="position:absolute, height:50%, width:100%">
</div>
);
}
// Stop the update timer when unmounting
componentWillUnmount () {
clearTimeout(this.timer);
}
}
export default Adbanner;
I haven't tested this. Let me know how it works out.

How would I go about using window.find() activate on that text only once

I use hack.chat a bit, and I saw that they have a bot, but the bot program wasn't working for me so I decided to make my own.
var finderBinder;
var searchFor = function(command){
finderBinder = window.find(command, true, true);
if(finderBinder){
if(command === "/hello"){
ws.send(JSON.stringify({cmd: "chat", text: "hello!"}));
}
else if(command === "/cry"){
ws.send(JSON.stringify({cmd: "chat", text: "wah waha wahhh"}));
}
else
{
console.log("it was found but it was not a command.")
}
}
else
{
console.log("Did not find the command");
}
}
var loopdeloop = 0;
while(loopdeloop === 0){
searchFor("/hello");
searchFor("/cry");
}
Now, the first part works if I just run that by itself on the page, and enter searchFor("/hello"); that would work, but if I wanted it to just automatically do that whenever a message popped up, I attempted the loop,(In a empty chatroom so it wouldn't spam a used room if it did) and it crashed my browser. I know why it did that. because it just checked forever, and it saw it forever so it kept on trying to do the code forever..
But how would I make it only run the searchFor when a new text showed up so it would run the text in it and if it was a command it would do the command? Or is there a better way to do this?
The simplest way to stop your function from looping to infinity (and beyond!) would be to call it once every X seconds/minutes/hours/lightyears.
Using setInterval(searchFor, 1000); where the second parameter is the time interval in milliseconds.
To pass a parameter to your searchFor function, you must create an anonymous function so it doesn't get called right away.
setInterval( function() { searchFor ("/hello"); }, 1000 );
This will call your function every ~1 second, although keep in mind there is some overhead to javascript and there will be a slight delay. Also be careful of looping your function too often, as it will be expensive, and browsers have a built in delay, for example, you will not be able to setInterval to 2 ms and have it function normally cross browser.
Edit: The more elegant solution of binding an event to a change in the textbox is also possible, depending on how the page is setup and your access to it, hard to answer without that structure known.

Categories

Resources