my function runs faster than the interval set - node.js

I have this code, which is supposed to send a message and add to a variable every 10 minutes
function btcb() {
const embed = new Discord.MessageEmbed()
.setColor('#FF9900')
.setTitle("Bitcoin block #"+bx.blocks.btc+" was mined")
.setAuthor('Block mined', 'https://cdn.discordapp.com/emojis/710590499991322714.png?v=1')
client.channels.cache.get(`710907679186354358`).send(embed)
bx.blocks.btc = bx.blocks.btc+1
}
setInterval(btcb,600000)
But it actually does it every 2-3 minutes instead. What am I doing wrong?

Youre better off setting the interval to 1 second and counting 600 seconds before resseting:
let sec = 0;
function btcb() {
if(sec++<600) return;
sec = 0;
const embed = new Discord.MessageEmbed()
.setColor('#FF9900')
.setTitle("Bitcoin block #"+bx.blocks.btc+" was mined")
.setAuthor('Block mined', 'https://cdn.discordapp.com/emojis/710590499991322714.png?v=1')
client.channels.cache.get(`710907679186354358`).send(embed)
bx.blocks.btc = bx.blocks.btc+1
}
setInterval(btcb,1000)

Related

how to implement checking for a timer on a webpage

I'm still learning, but I've been trying to build a faucet bot for 5minutebitcoin.com,
using selenium-webdriver in nodejs. And I've been trying to figure out how to implement a check, for the 5 minute timer. So the script would check to see if the timer is present, if it is then sleep for the remaining countdown. And if ther's no timer left on the countdown then proceed, with the script. So far I have
const { Builder, By, Key, until } = require('selenium-webdriver');
let chrome = require('selenium-webdriver/chrome');
let address = 'btcAddress';
let balanceUrl = 'http://5minutebitcoin.com/check-balance/?the99btcbfaddress=';
let claimBtcUrl = 'http://5minutebitcoin.com/';
async function main() {
while (true) {
let driver = new Builder()
.forBrowser('chrome')
.setChromeOptions(new chrome.Options().headless())
.build();
let getBalance = await driver.get(balanceUrl + address);
driver.manage().setTimeouts({implicit: 5000});
balanceText = await driver.findElement(By.css('div.row.info'));
console.log(await balanceText.getText());
try {
let minuteTimerText = await driver.findElement(By.css('timer'));
// assert(minuteTimerText = true);
return true
}
catch(err) {
console.log("\n Timer not ready: ");
sleep(5)
}
let claimBtc = await driver.get(claimBtcUrl);
driver.manage().setTimeouts({implicit: 5000});
submit = await driver.findElement(By.name('claim_coins')).click()
console.log("\n Submitting to faucet using: " + address + "\n\n");
await driver.quit();
}
};
main()
At the moment it does:
Unpaid address balance: 72705 Satoshis
Address seniority: 9 days
Seniority bonus: 5% on all direct payouts
Time until next seniority level: 5 days
Submits per 24 hours: 15 / 48
Timer not ready:
Submitting to faucet using:
And loops.....
It's supposed to do:
Get the address balance and log.
Then check to see if the timer is active.
And if the timer is still active wait till the timer runs out.
solve the captcha
Then click claim coins.
And repeat every 5 minutes.
I'll be using tesseract-ocr to solve the captcha

Session expired functionality for MERN stack project

I want to implement session expire functionality. so when the user stays on that page for more than 15 min then it should show an alert that the session is expired now. also, meanwhile, if someone copies that URL and pastes it to another tab/browser/incognito (where he was already logged in) or refreshes the page, it should not retake the countdown. for example, if it's in the middle of the countdown let's say 5 min left to reach 15min then after copy-pasting URl on another tab at that time it should start from 5min left then 4 min left, and so on without retaking the countdown from 15 min.
I am not sure what is the best way to implement this in the MERN stack project (should use any library or cookie or local storage) also with security?
I tried sample implementation but it does not work for cross-browser or for incognito it retakes the session also after 15min if I refresh the page countdown timer again starts. someone has a better example or suggestion regarding how to implement the functionality is really appreciated TIA :-)
My dummy implementation example -
countdowntimer.tsx file
const history = useHistory();
const [countdownSessionExpired, setCountdownSessionExpired] = React.useState(false);
React.useEffect(() => {
const countDownTime = localStorage.getItem(COUNTER_KEY) || 10;
countDown(Number(countDownTime), () => {
console.log("countDownTime:", countDownTime);
setCountdownSessionExpired(true);
});
}, [history]);
return (
<>
{countdownSessionExpired ? (
<div>sessoin is expired</div>
) : (
<div>view the page</div>
)}
</>
);
};
==================================================================================================
countdowntimer.utils.tsx file
export const COUNTER_KEY = "myCounter";
export function countDown(i: number, callback: Function) {
const timer = setInterval(() => {
let minutes = i / 60;
let seconds = i % 60;
minutes = minutes < 10 ? 0 + minutes : minutes;
seconds = seconds < 10 ? 0 + seconds : seconds;
// document.getElementById("displayDiv")!.innerHTML = "Time (h:min:sec) left for this station is " + "0:" + minutes + ":" + seconds;
console.log("Time (h:min:sec) left for this station is:", seconds, i--);
if (i-- > 0) {
localStorage.setItem(COUNTER_KEY, String(i));
} else {
localStorage.removeItem(COUNTER_KEY);
clearInterval(timer);
callback();
}
}, 1000);
}```

Node.js setTimeout() behaviour

I want a piece of code to repeat 100 times with 1 sec of delay in between. This is my code:
for(var i = 0; i < 100; i++){
setTimeout(function(){
//do stuff
},1000);
}
While this seems correct to me it is not. Instead of running "do stuff" 100 times and waiting 1 sec in between what it does is wait 1 sec and then run "do stuff" 100 times with no delay.
Anybody has any idea about this?
You can accomplish it by using setInterval().
It calls function of our choice as long as clearTimeout is called to a variable timer which stores it.
See example below with comments: (and remember to open your developer console (in chrome right click -> inspect element -> console) to view console.log).
// Total count we have called doStuff()
var count = 0;
/**
* Method for calling doStuff() 100 times
*
*/
var timer = setInterval(function() {
// If count increased by one is smaller than 100, keep running and return
if(count++ < 100) {
return doStuff();
}
// mission complete, clear timeout
clearTimeout(timer);
}, 1000); // One second in milliseconds
/**
* Method for doing stuff
*
*/
function doStuff() {
console.log("doing stuff");
}
Here is also: jsfiddle example
As a bonus: Your original method won't work because you are basically assigning 100 setTimeout calls as fast as possible. So instead of them running with one second gaps. They will run as fast as the for loop is placing them to queue, starting after 1000 milliseconds of current time.
For instance, following code shows timestamps when your approach is used:
for(var i = 0; i < 100; i++){
setTimeout(function(){
// Current time in milliseconds
console.log(new Date().getTime());
},1000);
}
It will output something like (milliseconds):
1404911593267 (14 times called with this timestamp...)
1404911593268 (10 times called with this timestamp...)
1404911593269 (12 times called with this timestamp...)
1404911593270 (15 times called with this timestamp...)
1404911593271 (12 times called with this timestamp...)
You can see the behaviour also in: js fiddle
You need to use callback, node.js is asynchronous:
function call_1000times(callback) {
var i = 0,
function do_stuff() {
//do stuff
if (i < 1000) {
i = i + 1;
do_stuff();
} else {
callback(list);
}
}
do_stuff();
}
Or, more cleaner:
setInterval(function () {
//do stuff
}, 1000);
Now that you appreciate that the for loop is iterating in a matter of milliseconds, another way to do it would be to simply adjust the setTimeout delay according to the count.
for(var i = 0; i < 100; i++){
setTimeout(function(){
//do stuff
}, i * 1000);
}
For many use-cases, this could be seen as bad. But in particular circumstances where you know that you definitely want to run code x number of times after y number of seconds, it could be useful.
It's also worth noting there are some that believe using setInterval is bad practise.
I prefer the recursive function. Call the function initially with the value of counter = 0, and then within the function check to see that counter is less than 100. If so, do your stuff, then call setTimeout with another call to doStuff but with a value of counter + 1. The function will run exactly 100 times, once per second, then quit :
const doStuff = counter => {
if (counter < 100) {
// do some stuff
setTimeout(()=>doStuff(counter + 1), 1000)
}
return;
}
doStuff(0)

nodejs - every minute, on the minute

How can I wait for a specific system time before firing ?
I want to fire an event when seconds = 0, i.e. every minute
while (1==1) {
var date = new Date();
var sec = date.getSeconds();
if(sec===0) {
Do Something()
}
}
You shouldn't do that, because with this while you will have a blocking operation. Also, there are better things to do in any JavaScript platform, like using setInterval/setTimeout functions.
The node docs for them are here.
A quick example of how to achieve what you want:
setInterval(function() {
var date = new Date();
if ( date.getSeconds() === 0 ) {
DoSomething();
}
}, 1000);
For a more fine grained control over scheduled processes in Node, maybe you should checkout node-cron.

How do I execute a piece of code no more than every X minutes?

Say I have a link aggregation app where users vote on links. I sort the links using hotness scores generated by an algorithm that runs whenever a link is voted on. However running it on every vote seems excessive. How do I limit it so that it runs no more than, say, every 5 minutes.
a) use cron job
b) keep track of the timestamp when the procedure was last run, and when the current timestamp - the timestamp you have stored > 5 minutes then run the procedure and update the timestamp.
var yourVoteStuff = function() {
...
setTimeout(yourVoteStuff, 5 * 60 * 1000);
};
yourVoteStuff();
Before asking why not to use setTimeinterval, well, read the comment below.
Why "why setTimeinterval" and no "why cron job?"?, am I that wrong?
First you build a receiver that receives all your links submissions.
Secondly, the receiver push()es each link (that has been received) to
a queue (I strongly recommend redis)
Moreover you have an aggregator which loops with a time interval of your desire. Within this loop each queued link should be poll()ed and continue to your business logic.
I have use this solution to a production level and I can tell you that scales well as it also performs.
Example of use;
var MIN = 5; // don't run aggregation for short queue, saves resources
var THROTTLE = 10; // aggregation/sec
var queue = [];
var bucket = [];
var interval = 1000; // 1sec
flow.on("submission", function(link) {
queue.push(link);
});
___aggregationLoop(interval);
function ___aggregationLoop(interval) {
setTimeout(function() {
bucket = [];
if(queue.length<=MIN) {
___aggregationLoop(100); // intensive
return;
}
for(var i=0; i<THROTTLE; ++i) {
(function(index) {
bucket.push(this);
}).call(queue.pop(), i);
}
___aggregationLoop(interval);
}, interval);
}
Cheers!

Resources