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.
Related
I have an Ajax call which I want run multiple times till it satisfies a particular if condition. The AJAX call gives you the job status-Running, Queued and Complete.
I am unable to get the Job status- Complete. After getting Running status it takes a couple of minutes to get the status Complete. So far I have tried the following JS. I also want to break the loop after the if condition has been met. I am also not sure if I should run the call for 100 times as it might take more than that. Thank you for your help.
My JS:
var pollForJob= gallery.getJob(jobId, function(job){
var jobStat=job.status;
console.log(jobStat);
if(jobStat=="Complete"){
alert("Complete");
} else {
// Attempt it again in one second
setTimeout(pollForJob, 1000);
console.log("still working");
console.log(jobStat);
}
}, function(response){
var error = response.responseJSON && response.responseJSON.message ||
response.statusText;
alert(error);
// Attempt it again in one second
setTimeout(pollForJob, 1000);
});
Like Jeremy Thille said, this is called long polling. A simple way of doing it is to create a function which makes the call out to the server. Then, if it fails, use setTimeout to queue up another request later.
function pollForJob() {
gallery.getJob(jobId, function(job) {
var jobStat = job.status;
if (jobStat == "Complete") {
alert("Complete");
} else {
// Attempt it again in one second
setTimeout(pollForJob, 1000);
}
}, function(response) {
var error = response.responseJSON && response.responseJSON.message || response.statusText;
console.error(error);
// Attempt it again in one second
setTimeout(pollForJob, 1000);
});
}
pollForJob();
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.
In JavaScript, I have written a method and I am executing this method for every 5 mins.After 15 mins , I am stopping this call.
var tChk ;
tChk = setInterval("test()", 5*60*1000);
setTimeout("timeOut(tChk)", 15*60*1000); // 15 mins time out
function timeOut(tChk) {
clearInterval(tChk);
}
function test() {
console.log("test");
}
How can I know whether my method is still executing or it expired because of timeout. . Is there any option in Chrome Dev tools where it shows the list of methods queued for execution?
Thanks.
function startTimer(){
return new Promise(function(resolve,reject){
var tChk = setInterval(test, 5*60*1000);
var count=0;
function test() {
console.log("test");
count++;
if(count>10){
clearInterval(tChk);
resolve();
}
}
function timeout(){
clearInterval(tChk);
reject('timeout');
}
setTimeout(timeout, 15*60*1000);
})
}
startTimer().then(function(){
console.log('count reached!');
}).catch(function(e){
console.log(e);
})
There is no way to list the timer method with pure javascript.
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
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.