3

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.

Farjad Hasan
  • 3,354
  • 6
  • 23
  • 38
  • Polling this frequently will cause server load. Possable solutions: Reduce polling frequency, use web-sockets instead, rent a better server – Steve Oct 29 '15 at 14:52
  • Although 2 users should not overload the server - what webserver are you using? Apache? – Steve Oct 29 '15 at 14:55
  • You could cache the data while you are at it... – ka_lin Oct 29 '15 at 14:57
  • @Steve yep, I am testing on Apache. If I want to use web sockets, I need to use Node.js? – Farjad Hasan Oct 29 '15 at 14:58
  • @NuttyProgrammer No need for Node.js, added PHP-based web socket references in my answer. – Mikel Bitson Oct 29 '15 at 15:02
  • `300ms` seems very little for a notification system. Usually users don't even notice if it's a `0ms` or a `5s` delay until they receive the notification. You should use at least a one second polling time if it's really about notifications (not chat or something that actually requires speed). – XCS Oct 29 '15 at 15:03
  • @Cristy I tried with 3s delayed but it still had issues. After that I tried another solution. `function load_notifications(){ $http.get('http://localhost:3000/load').success(function(data){ $scope.totalNotify = data.total; load_pictures(); }); }; load_pictures();` this makes it little better but I still wants to optimize it more. – Farjad Hasan Oct 29 '15 at 15:06
  • @Cristy If the notification comes from user interaction they'd notice a 5 or even 3 second delay. If they're just random notifications, I agree you could check every 10s or so. – Mikel Bitson Oct 29 '15 at 15:07
  • @NuttyProgrammer Hey Nutty! Did you have any luck? Need any further instruction? If you feel like any of the answers provided you with a better technique to accomplish the notifications, could you chose one as the answer? Thanks! – Mikel Bitson Oct 29 '15 at 17:40

4 Answers4

3

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.

Community
  • 1
  • 1
Mikel Bitson
  • 3,583
  • 1
  • 18
  • 23
  • I am trying hello world code. But I didn't get the telnet part. To open three terminals and run: 1) $ php bin/chat-server.php 2) $ telnet localhost 8080 3) $ telnet localhost 8080 – Farjad Hasan Oct 29 '15 at 19:58
  • The telnet part is just for testing. You won't need it. Simply run the first command (something like php bin/chat-server.php) and the web socket server is up and running! The guide shows you how to telnet to 8080 because that is where they setup their server in the guide, so you can monitor the web socket on port 8080 by telnetting to it. You'd want to setup your server on port 80 for web communications, just like typical websites. I'd recommend setting up an angularjs page and trying to connect to the server once you've run that php command, and then push something using $client->send($msg); – Mikel Bitson Oct 29 '15 at 20:08
2
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);
Alexander Elgin
  • 6,796
  • 4
  • 40
  • 50
2

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();
Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
0

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.

fos.alex
  • 5,317
  • 4
  • 16
  • 18
  • This isn't correct. Instead of monitoring a DB in real time, you fire a web socket push whenever a record is inserted or updated. This allows you to update the front-end in real time without any monitoring/real-time database features, and it operates in real time with no large server load. EDIT: That being said, I love firebase and angularfire. – Mikel Bitson Oct 29 '15 at 15:09
  • @MikelBitson if you don't mind, can you provide me a basic sample how the web socket push data to frontend on change in DB. – Farjad Hasan Oct 29 '15 at 15:11
  • If you have several nodes that update the DB that can get really messy with every node just notifying about changes all the time. – fos.alex Oct 29 '15 at 15:11
  • @fos.alex This is true, it can get complex. Using a single web socket server will remedy this- have all nodes push their updates to the web socket server, which pushes to all front-end clients. – Mikel Bitson Oct 29 '15 at 15:12
  • @NuttyProgrammer I've added a basic hello-world example for Rachet (PHP Web Socket Library) to my answer. – Mikel Bitson Oct 29 '15 at 15:18