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

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.

Related

Communicate from server to client side in Google Apps script

I am trying to write a Google Apps script which has a client and server side component. The client side component displays a progress bar. The client calls server side functions (which are called asynchronously), whose progress has to be shown in the client side progress-bar. Now, what I want is to be able to update the client side progress bar based on feedback from the server side functions. Is this possible?
The complexity is created due the the fact that JS makes the server-side calls asynchronously and hence I cannot really have a loop on the client side calling the functions and updating the progress bar.
I could of course split up the execution of the server side function in multiple steps, call one by one from the client side, each time updating the status bar. But I'm wondering if there's a better solution. Is there a way to call a client side function from the server side, and have that update the progress bar based on the argument passed? Or is there a way to access the client side progress-bar object from server side and modify it?
The way I've handled this is to have a middleman (giving a shout out now to Romain Vialard for the idea) handle the progress: Firebase
The HTML/client side can connect to your Firebase account (they're free!) and "watch" for changes.
The client side code can update the database as it progresses through the code - those changes are immediately fed back to the HTML page via Firebase. With that, you can update a progress bar.
Romain has a small example/description here
The code I use:
//Connect to firebase
var fb = new Firebase("https://YOUR_DATABASE.firebaseio.com/");
//Grab the 'child' holding the progress info
var ref = fb.child('Progress');
//When the value changes
ref.on("value", function(data) {
if (data.val()) {
var perc = data.val() * 100;
document.getElementById("load").innerHTML = "<div class='determinate' style='width:" + perc + "%\'></div>";
}
});
On the client side, I use the Firebase library to update the progress:
var fb = FirebaseApp.getDatabaseByUrl("https://YOUR_DATABASE..firebaseio.com/");
var data = { "Progress": .25};
fb.updateData("/",data);
Rather than tying the work requests and progress updating together, I recommend you separate those two concerns.
On the server side, functions that are performing work at the request of the client should update a status store; this could be a ScriptProperty, for example. The work functions don't need to respond to the client until they have completed their work. The server should also have a function that can be called by the client to simply report the current progress.
When the client first calls the server to request work, it should also call the progress reporter. (Presumably, the first call will get a result of 0%.) The onSuccess handler for the status call can update whatever visual you're using to express progress, then call the server's progress reporter again, with itself as the success handler. This should be done with a delay, of course.
When progress reaches 100%, or the work is completed, the client's progress checker can be shut down.
Building on Jens' approach, you can use the CacheService as your data proxy, instead of an external service. The way that I've approached this is to have my "server" application generate an interim cache key which it returns to the "client" application's success callback. The client application then polls this cache key at an interval to see if a result has been returned into the cache by the server application.
The server application returns an interim cache key and contains some helper functions to simplify checking this on the client-side:
function someAsynchronousOperation() {
var interimCacheKey = createInterimCacheKey();
doSomethingComplicated(function(result) {
setCacheKey(interimCacheKey, result);
});
return interimCacheKey;
}
function createInterimCacheKey() {
return Utilities.getUuid();
}
function getCacheKey(cacheKey, returnEmpty) {
var cache = CacheService.getUserCache();
var result = cache.get(cacheKey);
if(result !== null || returnEmpty) {
return result;
}
}
function setCacheKey(cacheKey, value) {
var cache = CacheService.getUserCache();
return cache.put(cacheKey, value);
}
Note that by default getCacheKey doesn't return. This is so that google.script.run's successHandler doesn't get invoked until the cache entry returns non-null.
In the client application (in which I'm using Angular), you call off to the asynchronous operation in the server, and wait for its result:
google.script.run.withSuccessHandler(function(interimCacheKey) {
var interimCacheCheck = $interval(function() {
google.script.run.withSuccessHandler(function(result) {
$interval.cancel(interimCacheCheck);
handleSomeAsynchronousOperation(result);
}).getCacheKey(interimCacheKey, false);
}, 1000, 600); // Check result once per second for 10 minutes
}).someAsynchronousOperation();
Using this approach you could also report progress, and only cancel your check after the progress reaches 100%. You'd want to eliminate the interval expiry in that case.

How to save things using Javascript

I am making a website where you can store financial things. Just for practise. Not to publice. So far I have making the part where you can add a new list. And fill in things. But of course if I refresh the page it will be gone. So how can I save the new made list?
You could store it in the Browser via a cookie or better, localStorage. But of course if the browser deletes the "personal data" or you use a different browser, the data is gone.
Normally you would set up a server (say, PHP) and save it in a database (e.g. MySQL), even if you use the application only on your own machine.
Try using cookies or WebStorage (localstorage or sessionstorage objects). And consider using HTTPS if you working with financial info
You could use Firebase. Works great if you're only doing small things.
Basically it allows you to store data online on their servers with the simple Firebase API.
Their tutorial should get you started:
Firebase 5 minute tutorial
I am very new to learning localstorage myself and since you said "storeing in the browser" , i guess the best comtemporary and hassle and hack free method is localstorage .
Here is a accordion i made which stores the state of the accordion(weather its open or closed).
FIDDLE HERE
JS ::
$(function () {
var initialCollapse = localStorage.collapse;
if (initialCollapse) initialCollapse = initialCollapse.split(",")
console.log(initialCollapse);
$(".collapse-headings>a").click(function () {
var div = $(this).parent();
div.toggleClass("close open");
$(".collapse-content", div).toggle("slow");
localStorage.collapse = $(".collapse-headings").map(function () {
return $(this).hasClass("open") ? "open" : "close"
}).get()
console.log(localStorage.collapse)
return false;
})
if (initialCollapse) {
$(".collapse-headings>a").each(function (i) {
var div = $(this).parent();
div.removeClass("close open").addClass(initialCollapse[i])
$(".collapse-content", div).toggle(initialCollapse[i] !== "close");
})
}
});
This might be a good starting point to understanding localstorge , but if you do a google search , you'll come across a ton of useful information such as cross browser compatibility and local storage limitation and fallbacks.

Overuse internet connection with app

I am creating android application, using the PhoneGap platform. I have tested the use of resources by the application and I noticed that uses a lot of free 3G. In comparison to an application such as whatsapp, using too much connection.
My app is a chat, and I use javascript to make requests to refresh messages. Following the javascript that takes care of this:
var refreshShout = setInterval(app.ajaxFunction, 1000);
[...]
ajaxFunction: function () {
var shoutbase = $('.shoutbox');
if (shoutbase) {
$.get('http://edonetwork.altervista.org/Magnitude/log.php', function (data) {})
.done(function(data) {
$(shoutbase).html(data);
})
.fail(function() {
$(shoutbase).html('<div class="alert-internet">Ops... Occorre una connessione ad internet per usufruire dell\'App!</div>');
});
}
}
In log.php page there are all existing messages taken with MYSQL query from the database of altervista.
Below is the query that is executed:
$dati=mysql_query(" SELECT * FROM `Shoutbox` ORDER BY `Shoutbox`.`ID` DESC LIMIT 0 , 30 ");
How can I limit the use of the internet? As currently is excessive! But I think all chat app continue to make requests but why are more performant?
Thank you.

What's the best way use caching data in js on client side?

My application receives data from the another server, using API with limited number of requests. Data changing rarely, but may be necessary even after refresh page.
What's the best solution this problem, using cookie or HTML5
WebStorage?
And may be have other way to solve this task?
As much as cross browser compatibility matters, cookie is the only choice rather than web storage.
But the question really depends on what kind of data you are caching?
For what you are trying, cookie and web-storage might not be needed at all.
Cookies are used to store configuration related information, rather than actual data itself.
Web storage supports persistent data storage, similar to cookies but with a greatly enhanced capacity and no information stored in the HTTP request header. [1]
I would rather say, it would be stupid to cache the entire page as cookie or web-storage both. For these purposes, server-side caching options might be the better way.
Update:
Quoting:
data about user activity in some social networks (fb, vk, google+)
Detect the web-storage features, using libraries like mordernizr and if does not exists fall back to cookie method. A simple example
if (Modernizr.localstorage) {
// browser supports local storage
// Use this method
} else {
// browser doesn't support local storage
// Use Cookie Method
}
[1]: http://en.wikipedia.org/wiki/Web_storage
I wrote this lib to solve the same problem:
Cache your data with Javascript using cacheJS
Here are some basic usages
// just add new cache using array as key
cacheJS.set({blogId:1,type:'view'},'<h1>Blog 1</h1>');
cacheJS.set({blogId:1,type:'json'}, jsonData);
// remove cache using key
cacheJS.removeByKey({blogId:1,type:'json'});
// add cache with ttl and contextual key
cacheJS.set({blogId:2,type:'view'},'<h1>Blog 2</h1>', 3600, {author:'hoangnd'});
cacheJS.set({blogId:3,type:'view'},'<h1>Blog 3</h1>', 3600, {author:'hoangnd'});
// remove cache with con textual key
// cache for blog 2 and 3 will be removed
cacheJS.removeByContext({author:'hoangnd'})
Here is an example of caching data from JQuery AJAX. So if you only want to make the call when you don't have the data yet, its really simple. just do this (example). Here we first check if we have the load information (keyed on line, location and shipdate), and only if we dont, we make the AJAX call and put that data into our cache:
var dict = [];
function checkCachedLoadLine(line, location, shipDate, callback) {
var ret = 0;
if(!((line+location+shipDate) in dict)) {
productionLineService.getProductionLoadLine(line, location, shipDate, callback);
}
return dict[line+location+shipDate];
}
...then in the call back write the value to the cache
function callback(data) {
if (!data) {
document.getElementById('htmlid').innerHTML = 'N/A';
} else {
document.getElementById('htmlid').innerHTML = data[0];
dict[data[2]+data[3]+data[4]] = data[0];
}
}

setInterval alternative

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.

Categories