setInterval alternative - javascript

In my app I am polling the webserver for messages every second and displaying them in the frontend.
I use setInterval to achieve this. However as long as the user stays on that page the client keeps polling the server with requests even if there is no data. The server does give an indication when no more messages are being generated by setting a variable.
I thought of using this variable to clearInterval and stop the timer but that didn't work. What else can I use in this situation?
I am using jquery and django. Here is my code:
jquery:
var refresh = setInterval(
function ()
{
var toLoad = '/myMonitor'+' #content';
$('#content').load(toLoad).show();
}, 1000); // refresh every 1000 milliseconds
});
html:
div id=content is here
I can access the django variable for completion in html with each refresh. How can I set clearInterval if at all ?
Note: stack overflow does not let me put is &gt &lt so html is incomplete
Thanks
Updated 03/16/2010
I must be doing something wrong. But cannot figure it out. Here is my script with clearTimer and it does not work.
var timer = null;
$(function(){
if ("{{status}}" == "False")
{
clearInterval(timer);
}
else
{
timer = setInterval(
function(){
var toLoad = '/myMonitor'+' #content';
$('#content').load(toLoad).show();}
,1000); // refresh every 1000 milliseconds
}
});
status is a boolean set in "views.py" (Django).
Thanks a bunch.

A couple people have already answered with specific resources to your problem, so I thought I would provide a bit of background.
In short, you want the server to push data to the browser to avoid extensive client-side polling. There isn't a good cross-browser way to support server push, so a common solution that requires much less polling is to use the Comet (another cleaning product, like AJAX) long-poll technique.
With Comet, the browser makes a request, and the server keeps the connection open without responding until new data is available. When the server does has new data, it sends it over the open connection and the browser receives it right away. If the connection times out, the browser opens a new one. This lets the server send data to the client as soon as it becomes available. As others have indicated, this approach requires special configuration of your web server. You need a script on the server that checks for data at an interval and responds to the client if it exists.
Something to keep in mind with this approach is that most web servers are built to get a request from a client and respond as quickly as possible; they're not intended to be kept alive for a long period of time. With Comet you'll have far more open connections than normal, probably consuming more resources than you expect.

Your clearInterval check is only checking when the document ready event is fired.
If the code you gave is exactly what's in the browser, then you're comparing the string "{{status}}" to the string "False". I'd rather watch paint dry than wait for that to evaluate as true.
What if your requests taking longer than 1 second to complete? : You'll flood your server with requests.
function update () {
$('#content').show().load('/myMonitor'+' #content', function (response, status) {
if (!/* whatever you're trying to check*/) {
setTimeout(update, 1000);
};
});
};
$(document).ready(function () {
update();
});
Is closer than where you were, but you still need to work out how you're going to decide when you want to stop polling.

Related

How to insert into database every x seconds, but that the user cannot change time to the inspect element?

I want to insert 1 point into the database every x seconds, but I don't want to allow a user that he can speed up that time into inspecting element. How can I do that?
var time = 1;
var interval = setInterval(function() {
if (time != time + 1) {
//some ajax code for sending points into database
time++;
}
}, 5000);
This code is what I looking for but user easy can change this 5000 to etc. 500 and speed up the process of getting point. Is there any way to prevent the user from changing that time?
Assuming that your ajax calls a PHP page, you should rate limit within the PHP (server-side) so that it cannot be modified by the user.
As it has been pointed out in the comments to your question, this task isn't well suited to ajax as it will constantly open and close connections which can degrade network performance and could trigger a WAF to start blocking those requests. You should use a WebSocket instead or send your data in bulk via ajax at a slower rate.

How to optimize $interval for real time notifications in Angularjs?

I am working on a social networking site. I have used following code to show the total notifications count in real time for a user.
Code:
function load_notifications(){
$http.get('http://localhost:3000/load').success(function(data){
$scope.totalNotify = data.total;
});
};
load_pictures();
$interval(function(){
load_notifications();
},300);
basically, this code checks the DB continuously at a given interval and if there is some change, it update the $scope value. But when I tried to check it with two different user in different browsers, it chokes the browser because of polling requests.
Is there any way to improve this method or have any other better alternative?
I am building my application using PHP and AngularJS. But I am open to other options for this module too.
This should be done using web sockets, not a polling ajax request.
JS: AngularJS and WebSockets beyond
PHP: How to create websockets server in PHP
Specifically, for web sockets using PHP, I would use Rachet.
A starting point for the PHP would be here: http://socketo.me/docs/hello-world
This hello world tutorial shows you basic javascript and PHP for interacting through Rachet.
awaitingResponse = false;
function load_notifications() {
if(!awaitingResponse) {
awaitingResponse = true;
$http.get('http://localhost:3000/load').then(function(response) {
$scope.totalNotify = response.data.total;
awaitingResponse = false;
}, function() {
awaitingResponse = false;
});
}
}
load_pictures();
$interval(load_notifications, 3000);
You could wait for 300 milliseconds after the answer was received, like this:
function load_notifications(){
$http.get('http://localhost:3000/load').success(function(data){
$scope.totalNotify = data.total;
setTimeout(function() {
load_notifications();
}, 300);
});
};
load_pictures();
load_notifications();
If you only use websockets, you will need to run a query every time to determine if anything has changed. I propose, use a real time DB.
You could use RethinkDB or Firebase with AngularFire. Those are realtime databases and will notify you when there is an update to any of those fields.
If you use RethinkDB, then you will also need to implement a websocket solution to notify the browser.

Check/Log how much bandwidth PhantomJS/CasperJS used

Is it possible to check/log how much data has been transferred during each run of PhantomJs/CasperJS?
Each instance of Phantom/Casper has a instance_id assigned to it (by the PHP function that spun up the instance). After the run has finished, the amount of data transferred and the instance_id will have to make its way to be inserted into a MySQL database, possibly via the PHP function that spawned the instance. This way the bandwidth utilization of individual phantomjs runs can be logged.
There can be many phantom/casper instances running, each lasting a minute or two.
The easiest and most accurate approach when trying to capture data is to get the collector and emitter as close as possible. In this case it would be ideal if phantomjs could capture that data that you need and send it back to your PHP function to associate it to the instance_id and do the database interaction. Turns out it can (at least partially).
Here is one approach:
var page = require('webpage').create();
var bytesReceived = 0;
page.onResourceReceived = function (res) {
if (res.bodySize) {
bytesReceived += res.bodySize;
}
};
page.open("http://www.google.com", function (status) {
console.log(bytesReceived);
phantom.exit();
});
This captures the size of all resources retrieved, adds them up, and spits out the result to standard output where your PHP code is able to work with it. This does not include the size of headers or any POST activity. Depending upon your application, this might be enough. If not, then hopefully this gives you a good jumping off point.

CherryPy kill process if not pinged in time

Is there a way to have CherryPy (running on :8080, it's only function being a listener for SIGUSR1) kill a process if it hasn't been pinged in a certain number of seconds?
Certainly the Python code for process killing is not in question, simply the way CherryPy would detect the last ping, and constantly compare it to the current time - Killing a process if it hasn't been pinged in a certain number of seconds.
Note that if Javascript is doing the pinging (via setInterval()), an infinite loop within the CherryPy code would cause the .ajax() request to hang and/or timeout, unless there is a way to have .ajax() only ping and not wait for any type of response.
Thanks for any tips you guys can provide!
Mason
Ok, so the answer was to set up two classes, one that updates the time, the other that constantly checks if the timestamp hasn't been updated in 20 seconds. This is ULTRA useful when it comes to killing a process once your user leaves a page, if the entire site isn't built on CherryPy. In my case, it is simply sitting on :8080 listening for JS pings from a Zend project. The CherryPy code looks like:
import cherrypy
import os
import time
class ProcKiller(object):
#cherrypy.expose
def index(self):
global var
var = time.time()
#cherrypy.expose
def other(self):
while(time.time()-var <= 20):
time.sleep(1)
print var
os.system('pkill proc')
cherrypy.quickstart(ProcKiller())
The JS that pings is literally as simple as:
<script type="text/javascript">
function ping(){
$.ajax({
url: 'http://localhost:8080'
});
}
function initWatcher(){
$.ajax({
url: 'http://localhost:8080/other'
});
}
ping(); //Set time variable first
initWatcher(); //Starts the watcher that waits until the time var is >20s old
setInterval(ping, 15000); //Updates the time variable every 15s, so that while users are on the page, the watcher will never kill the process
</script>
Hope that this helps someone else looking for a similar solution to process killing once users leave a page!
Mason

Listener on Javascript/Jquery

I have a web service where I fetched my data and populate it in my client. As of now, I have a button that will fetch data from the web service when clicked using ajax get. On my web service, I have a maintenance where I will be able to add, edit or delete data. What I want to do is to have my client automatically fetched data from my web service everytime I add, edit, or delete data, so it will show accurate data to the client.
Here's what I'm thinking. On my web service, i will have a json that will tell true/false whether the data has been updated (will be fetched by the client). So every add, edit, delete will turn that to true, and every time the client fetched that data, it will become false.
Now, I need to have a javascript/jquery listener that will listen to any change in that json (the true or false). I need to have that listener run every second? Is it possible?
Thanks.
EDITED:
I've been rereading my post, and it hits me, I'm just thinking with only one client in my mind. Every add,edit,delete in my web service will turn the "updated" to true, and everytime I get a request for the data, I'll set it to false. But how about the other clients? When they sent a request, it's already false, so they will not update it. Any ideas? Thanks
You can do this using two aproaches:
Web sockets; or
setInterval function.
Here is an example of setInterval().
// just a control var...
var gen = 1;
// call the function repeatedly in 5 seconds of interval
// this call returns an id that can be used to stop the calls
var id = setInterval(function(){
// function body...
alert( "making an ajax request...(" + gen + ")" ); // here you call your webservice
gen++;
// just want to stop it, but you wont need this.
if ( gen == 10 ) {
clearInterval( id );
}
}, 5000 ); // 5000 miliseconds == 5 seconds
Some links:
jsFiddle: http://jsfiddle.net/davidbuzatto/EyCSb/
https://developer.mozilla.org/en/DOM/window.setInterval
https://developer.mozilla.org/en/DOM/window.clearInterval
You've got two HTTP options: polling the server, or using a comet request. If you're polling, it might work better to include the last updated time in the request so the server can filter any events older than that time. That way, you don't need to save an extra flag for every event for every client.

Categories