How to make debounce in js - javascript

I have a function like below in Vuejs.
When you click button, 'start()' runs and function rn() runs also.
But 'const command' is being changed during 0.1sec, 3sec, 2sec or 2sec on just one button click.
That is 'button' is clicked just one, but 'command' is being changed a lot on short time.
But when the command isn't changed more than 3sec, I hope the Axios post runs.
Even though I tried using Lodash debounce, I have not found the solution.
Could you help me how to solve this? Thank you so much for reading.
<template>
<button #click="start()">Start</button>
</tempalte>
methods:{
start() {
..
..
..
function rn() {
const command = something..
..
axios.post('localhost:4000', {data: command})
}
}
}

Do it naive way.
const ELAPSE_TIME = 3000; // 3 second
let oldCommand;
let lastTime;
function update() {
if (buttonIsPressed) {
const command = getCurrentCommand();
if (command !== oldCommand) { // command has changed
lastTime = new Date().getTime();
} else { // command has not changed
let now = new Date().getTime();
let duration = now - lastTime;
if (duration > ELAPSE_TIME) { // already 3 second
postUpdate();
lastTime = now - ELAPSE_TIME;
}
}
}
}
setInterval(update, 100);

Related

How to run function for specific time and sleep for a specific time?

I want to run calculateSomething function for a specific period of time, for example for 1 minute which this function receive messages from MQTT protocol. After 1 minute, this function will sleep or stop receiving data from MQTT for 1 minute, then start to run again.
client.on('message', function (topic, message) {
calculateSomething(topic, message);
})
function calculateSomething(top, param) {
let graph = new Graph();
if(top === 'togenesis') {
graph.addEdgetogenesis(param.toString())
} else if (top === 'DAG'){
graph.addEdge(param.toString())
}
}
I have tried setInterval() but it keep run the function repeatly but I don't want to repeat the function because it is in real time. I also have tried setTimeout() but this only delay for the first time.
Any ideas please how could solve it? thanks in advance.
Try this, the execution of your function is subordinated by a boolean variable that I have named start which serves to keep the function operational (start = true) or not (start = false). The setInterval cycles for one minute and alternates the state of the boolean variable start.
client.on('message', function (topic, message) {
calculateSomething(topic, message);
})
var start = true;
setInterval(function(){
if(start){
start = false;
} else {
start = true;
}
}, 60000); //1 minute
function calculateSomething(top, param) {
if(start){ //the function is executed only if start is true
let graph = new Graph();
if(top === 'togenesis') {
graph.addEdgetogenesis(param.toString())
} else if (top === 'DAG'){
graph.addEdge(param.toString())
}
}
}

ReactJS useState not updating momentJS prop

I am coding a CRM app and there's a asnyc function for gettingTrackers and it working well. There's another function called calculateStartTime and this function suppose to calculate momentJS variable and set it but this is not updating.
useEffect(() => {
async function gettingTrackers() {
await getTrackers(null, null);
}
gettingTrackers();
calculateStartTime();
}, []);
const [startTime, setStartTime] = useState(moment().format("YYYY-MM-DD"));
const [endTime, setEndTime] = useState(moment().format("YYYY-MM-DD"));
const calculateStartTime = () => {
const dateOfMay = moment("2020-05-01");
const now = moment();
let timeTheStart = null;
let timeTheEnd = null;
if (now.add(-32, "d").diff(dateOfMay) <= 0) {
timeTheStart = dateOfMay.format("YYYY-MM-DD")
timeTheEnd = moment().add(-2, "d").format("YYYY-MM-DD");
} else {
timeTheStart = moment().add(-32, "d").format("YYYY-MM-DD");
timeTheEnd = moment().add(-2, "d").format("YYYY-MM-DD");
}
console.log("calculating...")
console.log("start time > ", timeTheStart)
console.log("end time > ", timeTheEnd);
setStartTime(moment(timeTheStart).format("YYYY-MM-DD"))
setEndTime(moment(timeTheEnd).format("YYYY-MM-DD"))
// these 2 logs prints initial value, not updated value.
console.log(startTime);
console.log(endTime)
}
The problem is that I have to send startTime and endTime to another ReactJS component, and it sends first initial today value every time. When I call calculateStartTime it logs
calculating...
start time > 2020-06-07
end time > 2020-07-07
But when I click to button for another component, I print these variables and its output;
2020-07-09
2020-07-09
as initial values. I log them with using startTime and endTime as I described in useState
What I am missing on this problem? Is there any memory-leak to not-working?
Edit:
const goToResultButton = (event, data) => {
event.preventDefault();
console.log("start time > ", startTime)
console.log("end time > ", endTime)
}
Thanks in advance!
With the below code block, you are setting the state and immediately you are trying to access the updated value, but state updates done in async fashion. You will get the latest value in the next re-render.
...
setStartTime(moment(timeTheStart).format("YYYY-MM-DD"))
setEndTime(moment(timeTheEnd).format("YYYY-MM-DD"))
// these 2 logs prints initial value, not updated value.
console.log(startTime);
console.log(endTime)
...
You can use a useEffect to log or do something with latest values of startTime and endTime.
useEffect(() => {
console.log("startTime", startTime);
console.log("endTime", endTime);
}, [startTime, endTime]);

Push function is not working properly localStorage Javascript vanilla

I am doing a time-to-click game as you can imagine the fastest time would be the first place. I just want to have 3 scores. and have it on localstorage but every time I start a new game the actual score resets its value and it doesnt generate other scores. the 3 scores should have as value 0. I tried to push them as arrays but push function is not working well. at this point I am stuck. I dont know what to do. If u may help me, I would be really grateful, thanks!
let times = Array.from({
length: 3
})
let interval2;
// Timer CountUp
const timerCountUp = () => {
let times = 0;
let current = times;
interval2 = setInterval(() => {
times = current++
saveTimes(times)
return times
}, 1000);
}
// Saves the times to localStorage
const saveTimes = (times) => {
localStorage.setItem('times', JSON.stringify(times))
}
// Read existing notes from localStorage
const getSavedNotes = () => {
const timesJSON = localStorage.getItem('times')
try {
return timesJSON ? JSON.parse(timesJSON) : []
} catch (e) {
return []
}
}
//Button which starts the countUp
start.addEventListener('click', () => {
timerCountUp();
})
// Button which stops the countUp
document.querySelector('#start_button').addEventListener('click', (e) => {
console.log('click');
times.push(score = interval2)
getSavedTimes()
if (interval) {
clearInterval(interval);
clearInterval(interval2);
}
})
This:
// Button which stops the countUp
document.querySelector('#start_button').addEventListener('click', (e) => {
Probably should be this:
// Button which stops the countUp
document.querySelector('#stop_button').addEventListener('click', (e) => {
...considering you're already attaching an event-handler to start's 'click' event in the previous statement, and no-one would use #start_button as the id="" of a stop button.

removing cookies using javascript is not done immediatly

I am currently working with a javascript that is supposed to remove some unwanted cookies, but for some reason aren't they removed when told to?..
only after certain amount of times trying to remove them, they seem to be removed.. some sort of delayed effect?
here is the code:
const name = 'test_u';
const name1 = 'test_te_s';
function eraseCookie(name) {
document.cookie = name+'=; Max-Age=-99999999;';
}
function removeCookies(cookieA, cookieB) {
setInterval(function() {
if (document.cookie.includes(cookieA) || document.cookie.includes(cookieB))
{
eraseCookie(cookieA);
eraseCookie(cookieB);
var date = new Date();
var timestamp = date.getTime();
console.log(timestamp)
}
},10000);
}
removeCookies(name, name1);
example from console log output:
1555420706478
1555420716477
1555420726487
1555420736487
1555420746497
1555420756487
It runs 6 times before its removed? but why though?
why aren't they removed immediately?
Because you have setInterval which means that that code will be run after some time that you provide, and keep repeating it by that interval. So just remove that setInterval:
function removeCookies(cookieA, cookieB) {
if (document.cookie.includes(cookieA) || document.cookie.includes(cookieB)) {
eraseCookie(cookieA);
eraseCookie(cookieB);
var date = new Date();
var timestamp = date.getTime();
console.log(timestamp)
}
}
And if you want to keep repeating it try this one:
removeCookies(name, name1);
setInterval(() => {
removeCookies(name, name1);
}, 10000);
or
function removeCookies(cookieA, cookieB) {
if (document.cookie.includes(cookieA) || document.cookie.includes(cookieB)) {
eraseCookie(cookieA);
eraseCookie(cookieB);
var date = new Date();
var timestamp = date.getTime();
console.log(timestamp)
}
setInterval(() => {
removeCookies()
}, 10000);
}
removeCookies(name, name1);
so it will first call removeCookies, and then it will keep repeating.

how can I add the ticking clock to my div in an existing code?

It's actually a follow up to this question I want to display elements from json based on their time and duration and interval is interupted by settimeout - I accepted the answer there made by #Daniel Flint - his code is quite clear and can be found here http://jsfiddle.net/nauzilus/rqctam5r/
However, there's one more thing that I wanted to add - a simple div <div id="time"></div> that would contain a new date time object initialized during opening the page and then it being incremented every second just to show the current time constantly. I thought about writing there a javascript:
var actualTime = new Date(substractedDate); // taken from the server
function updateTimeBasedOnServer(timestamp) {
var calculatedTime = moment(timestamp);
var dateString = calculatedTime.format('h:mm:ss A');
$('#time').html(dateString + ", ");
};
var timestamp = actualTime.getTime();
updateTimeBasedOnServer(timestamp);
setInterval(function () {
timestamp += 1000; // Increment the timestamp at every call.
updateTimeBasedOnServer(timestamp);
}, 1000);
(I provide the time of the server as a timestamp there).
I just noticed that there is a slight mismatch between displaying the time in my div and between the text appearing on the screen, possibly because I increment both of the values in two different places.
So my question is - how can I "merge" #Daniel Flint's code with mine and increment both values only in one place?
One thing that jumps out here:
timestamp += 1000;
setTimeout/setInterval aren't guaranteed to run at precisely the delay you've entered. Run this in your browsers console:
var last = Date.now(),
time = function() {
var now = Date.now();
console.log(now - last);
last = now;
},
id = setInterval(time, 1000);
On my Mac at home (Chrome/FireFox) it was anywhere from 990 to 1015. Windows machine at work is a bit better (995-1002), but IE was getting up to 1020. It's not a huge difference, but it's not nothing.
So code needs to be able to handle not running exactly every 1000ms. That's why I was running the timer at 500ms intervals, and checking if the start time was less-than-equal to the current time.
I've rejigged the demo to show the time and message in sync:
(function() {
var messages = [];
var time = document.getElementById("current-time");
var display = document.getElementById("message");
function check() {
showMessage(currentMessage());
showTime();
}
function currentMessage() {
var message = null;
if (messages.length) {
var now = toTheSecond(new Date());
var start = toTheSecond(new Date(messages[0].start_time));
var end = toTheSecond(new Date(start.getTime() + ( messages[0].text_duration * 1000 )));
if (start <= now) {
if (end <= now) {
// done with the current message...
messages = messages.slice(1);
// ...but check if there's another one ready to go right now
message = currentMessage();
}
else {
message = messages[0];
}
}
}
return message;
}
function toTheSecond(date) {
date.setMilliseconds(0);
return date;
}
function showMessage(message) {
if (message) {
display.textContent = message.text_content;
}
else {
display.textContent = "no messages";
}
}
function showTime() {
time.textContent = new Date().toLocaleString()
}
function getMessages() {
setTimeout(function() {
var now = new Date();
messages.push(
{"text_content":"aaaaa","text_duration":5,"start_time": new Date(now.getTime() + 3000).toISOString()},
{"text_content":"aawwaaaaa","text_duration":5,"start_time": new Date(now.getTime() + 10000).toISOString()},
{"text_content":"bbaawwaaaaa","text_duration":5,"start_time": new Date(now.getTime() + 15000).toISOString()}
);
}, 1000);
}
setInterval(check, 500);
getMessages();
})();
<span id="current-time"></span> <span id="message">Hello there!</span>
(Putting the code here as well because I recall SO want code in the answers so it's controlled, but there's a demo here: http://jsfiddle.net/nauzilus/ymp0615g/).
This probably isn't as efficient as it could be; the message text is being set every iteration which might cause repaints/reflow. But then again setting the time stamp is going to do that anyway, so meh :)

Categories