I'm working on a chat application, which polls the server at a timeout.
The timeout increases if, over time, there hasn't been any recent activity.
The function loadNew() performs an ajax call to the server, which responds with message data.
pollTimeoutTime = 500;
function poll() {
pollTimeout = setTimeout(function(){
loadNew();
if (!new_messages_count) {
//Increasing delay between polls as no messages are incoming to a maximum of 1 minute/60 seconds
if (pollTimeoutTime < 60000) pollTimeoutTime = pollTimeoutTime * 1.25;
}
else {
//Reset delay between poll to default of 0.5 seconds
pollTimeoutTime = 500;
}
poll();
},pollTimeoutTime);
}
The problem I'm having is that the timeout function does not wait for the function loadNew() to complete, which causes the same poll to be sent twice or more if the timeout is lower than the time it takes for the ajax call in the function to complete.
The server thus responds with the same data multiple times, which leads to duplicative display of messages in the chat.
Is there a way to make the timeout only trigger after loadNew() has finished fetching and displaying the data?
EDIT: after using #Brad M's answer, it doesn't duplicate messages anymore. I would still like to have a way to call for a poll after the user submits a message, so the new message is displayed immediately. This would interfere with the timeout set in loadNew(), which would cause messages to be duplicated again. Could you think of a way to get that working?
Without seeing your loadNew function, an easy fix might be to change that function to return your ajax call (return $.ajax({...});) and change the code you posted to this:
pollTimeoutTime = 500;
function poll() {
pollTimeout = setTimeout(function () {
loadNew().done(function (result) {
if (!new_messages_count) {
//Increasing delay between polls as no messages are incoming to a maximum of 1 minute/60 seconds
if (pollTimeoutTime < 60000) pollTimeoutTime = pollTimeoutTime * 1.25;
} else {
//Reset delay between poll to default of 0.5 seconds
pollTimeoutTime = 500;
}
poll();
});
}, pollTimeoutTime);
}
Use ajax callback functions such as success or complete to trigger a new poll.
Related
I want to render JavaScript function in every 500ms using node Cronjobs.
But I could find function for every 1 second as below.
cron.schedule("*/1 * * * * *", function() {
console.log("running a task every 1 second");
});
Is there anyway to run function on every 500ms using node Cronjob?
Setting a cron job to execute that frequently is not possible, and for good reason - a task executing that frequently shouldn't be done using a cron.
Instead, you can use Timers with Node.js:
function myFunc(arg) {
console.log("Argument received: " + arg);
}
setTimeout(myFunc, 500, "some message"); // Executes every 500ms.
Timers can also be instantiated into a variable:
const timeoutObject = setTimeout(() => {
console.log("I will print every 500ms!");
}, 500);
clearTimeout(timeoutObject);
lets say a website receives some data from users continuously. I want it to alert() users if it haven't received data from users in as long as 5 seconds.
this is How I'm trying to do it:
countDown = 5000
if(//some data received from user){
countDown = 5000
}
setTimeout(
function() {
alert('no data in 5 seconds')
}, countDown);
}
well it's not working because It can't set countDown to 5 sec every time It receives data from users, So How can I do this?
and since the data from user comes continuously I guess it wouldn't be good for performance to run a new setTimeout() and destroy the old one every time.(?)
This would be more of a recursive function that checks if there is any data. If not, it makes a function that runs in five seconds. If the data is still not there, you repeat the process.
let countDown = 5000
function someFunction() {
//this is called when you recieve data
timeoutFunc();
}
function timeoutFunc() {
setTimeout(
function() {
if (//still don't have new data) {
alert('no data in 5 seconds');
timeoutFunc();
}
}, countDown);
}
}
I'm running a 3 minutes timeout and in that timeout i am running another function at particular durations.But when i'm trying to cancel the timeout its still running and the function inside it is still getting executed.Here's my code
$scope.time = 180000;
var timer = function() {
if ($scope.time > 0) {
$scope.time -= 1000;
var durations = [170000, 150000, 130000, 110000, 90000, 70000, 50000, 30000, 10000];
if (durations.includes($scope.time)) {
dataService.acceptNotify(payload).then(function(response) {
console.log(response);
if (response.data.success === true) {
$mdToast.showSimple(response.data.msg);
$mdDialog.hide();
$timeout.cancel(timeout);
}
})
}
$timeout(timer, 1000);
} else {
$mdDialog.hide();
}
}
var timeout = $timeout(timer, 1000);
You are just not capturing the timer instance into your variable, hence not cancelling it.
Try changing this line in your code:
$timeout(timer, 1000);
to
timeout = $timeout(timer, 1000);
I believe timeout is happening but you are not able to observe it. I see you are calling function timer after every 1 sec with this code
var timeout = $timeout(timer, 1000);
but you are canceling it after getting the response api and in meantime there would have been many instance started which will call that many time. so actually it's cancelling but after few times.
For example, if you get response in 20 sec, then it would be cancelled after calling api 20 times as your code is such.
I can help you with right code if you tell me what you want to do above
Just remove below code which you are using above else block.
$timeout(timer, 1000);
It will work for you.
I have this function. Basically it searches data from database and does something with it. In this demo it just increases counter.
exports.fullThreads = function(){
return new Promise((resolve, reject) => {
MongoClient.connect(mongoUrl, (err, db) => {
var fullThreads = db.collection('tmp_fullThreads'),
threadPages = db.collection('tmp_threadPages').find();
var counter = 0;
threadPages.on('data', (doc) => {
setTimeout(function(){
counter++;
}, 200)
});
threadPages.on('end', () => {
console.log('end');
console.log(counter);
});
});//connect
});//promise
}//fullthreads
In this example I expected that it would call for data, wait 200ms, and then increase counter. Once it reaches the end, it would end. However it is different. on('end') is called before on('data') actually finished. I guess that is because it didn't return value immediately. So this setTimeout function is not a way to go. However I have a real problem here. This is simply way too fast and in real life code, this wouldn't increase counter, it would call foreign API which doesn't accept so many calls in so little time, so I wanted to make a delay between each call, how is this done properly?
Then you would need some kind of queu
eg:
queuTasks = [];
queuTasks.push("Task1");
queuTasks.push("Task2");
function doTasks(){
// Do your task
if(queuTasks.length > 0){
console.log(queuTasks[0]);
queuTasks.splice(0,1); // Remove it from the queu
}
setTimeout(function(){ doTasks();}, 1000);
}
This is just some quick code i made, may not work out of the box. But think you get the idea.
I know this is not entirely what you were asking about
This is my workaround:
var threadPages = db.collection('tmp_threadPages').find();
var delay = 0;
function test(doc, delay){
setTimeout(function(){
console.log(delay);
}, delay)
}
threadPages.on('data', (doc) => {
test(doc, delay);
delay += 100;
});
It works well if you do not need to bind proper events to on('end method. Basically it increases delay per request, otherwise it would fire all of them at once. This makes code go slower and it wouldn't overkill API with too many requests per second.
I have the following scenario:
I have a javascript ajax function loadCars() that needs to be called after the page loads in 10 seconds, and then every 60 seconds.
The below is what I have tried so far:
setTimeout(function(){setInterval(function(){loadCars()}, 60000)}, 10000);
What is happening is that the function is being called after 10 seconds but never again, what am I missing?
You need to call loadCars on setTimeout and on setInterval.
setTimeout(function() {
console.log('first 10 secs');
// loadCars();
setInterval(function() {
console.log('60 secs has passed');
// loadCars();
}, 60000);
}, 10000);
console.log('page loaded');
I don't agree with the answers given because they use setInterval or don't wait for the ajax call to be finished. IMO your should set a new timeout only when the function loadcars (and the ajax call) has finished.
Example:
function loadCars () {
// ajax call happens here
$.ajax()
.then(function(){
// call the function here
setTimeout(function(){
loadCars();
// wait a minute after you recieved the data
}, 60000)
})
}
// wait 10 seconds
setTimeout(function(){
loadCars();
}, 10000)
The advantage if this is that it will only start setting a new timeout when the HTTP request is finished and prevent the function from getting out of sync. If you use setinterval in combination with an ajax call then the next ajax call will happen in 60 seconds even if the current one is delayed for 10 seconds (and you don't want that).
You can call setTimeout(loadCars, 60000) in your loadCars() method that way you call it once initially with setTimeout 10 seconds then from that point it sets a timeout for 1 minute out every time it executes...
function loadCars()
{
//code
setTimeout(loadCars, 60000);
}
setTimeout(loadCars, 10000);
If you want the next timeout to be scheduled only after ajax call is completed then either make a synchronus ajax call or put the setTimeout() in your success callback of your ajax call...The latter being the better option.
To get more control over timings and function calls you could specify them all this way:
function loadCars() {
$('#log').append('Cars loaded<br />');
};
function loadManufacturers() {
$('#log').append('Manufacturers loaded<br />');
};
function loadCustomers() {
$('#log').append('Customers loaded<br />');
};
function loadContent(delays, functions) {
if (functions.length) {
setTimeout(function () {
functions.pop()();
loadContent(delays, functions);
}, delays.pop());
};
};
loadContent([3000, 2000, 1000], [loadCars, loadManufacturers, loadCustomers]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p id="log"></p>
Playground