Notifications: the other approach

11

A normal problem: notifications or updates that have to be displayed on a website, but it’s kind of overloading the backend. But as long as the page is open: please update the status dynamically (if necessary) without reloading the page.

I can hear you think: AJAX! Yes, I’ll use AJAX for sure. But there is a little problem when it comes to how up-to-date you want these notifications to be without overloading the backend of the website.

In this article I’ll approach pushing notifications from another perspective, regulating them in the backend rather than the frontend.

notifications

Download
Get the code of this post
Example
Watch the example video

Most of the applications that use AJAX to update the information that is on the screen use a simple request that fire every once in a while. This doesn’t really make the notification instant and can cause the Javascript to make more calls than necessary to the server.

Expanding the interval time of the calls would lessen the requests, but that would take away a bit of the notification functionality don’t you think? When there is something to notify: notify me!

With these problems in mind, there might be various solutions. A solution someone told me about got me interested; rather than letting Javascript determine whether to make a call to the server, let the server do it.

How it works:

How are we going to make the backend (in this case PHP) say when the frontend has to update?

The solution is quick and easy: only return information if PHP has some, and let PHP tell the frontend to reload. Simply put: if there is an answer: go and reload.
To make this a bit more clear, I’ve put together the following work flow:

  • Frontend notifies the backend that it wants information.
  • The backend goes in a loop waiting for information to give back to the frontend.
  • If in the meantime information is available: return the results.
  • The backend gives his answer (if available) and tells the frontend to do another request.

This approach is a bit different from letting Javascript interval the requests and making it load PHP the whole time.

Getting started:

In this example I am going to make a simple page that shows text from a txt file on the server and changes the text once changes are made on the server.

First we need a bit of code to get everything off the ground.

Start with this super easy HTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>Notification test</title>

	<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js?ver=1.3.2'></script>
	<script type="text/javascript" src="notification/notification.js"></script>
</head>
<body>
	<div id='content'>
		<h1>Notification test</h1>

		<p>
			This example will notify the user when changes have been made to updates.txt.
		</p>

		<div id='notify'>

		</div>		

	</div>
</body>
</html>

Nothing too complicated right? I won’t go into details what I did here.

We are going to use jQuery for its AJAX functions (which are so convenient and make clean code.)

The next step would be to output information in the #notify element.

The Javascript code:

What do we need in the Javascript:

  • A function to make a request to the backend.
  • In the callback of the jQuest AJAX function we need to load the notifications and output them if they exist.
  • When callback is called: repeat the cycle.

Create a folder called “notification” and in that folder create the file: “notification.js”. From the root where the HTML file is in it would be: “notification/notification.js”. We’ll use this folder to add other files too.

The basic Javascript I got is:

var notification = {

	request_url: "notification/notification_request.php",

	do_request: function() {

	}

}

notification.do_request();

Notice that I separated the request URL from the actual AJAX call that will be the next step. I always to this so I can change this URL with ease, without changing all the code. Request URL change some times, and you don’t want to have to mess around in the code too much.

Now to fill the do_request function, we’ll make a post request to the URL and expect JSON back as its output. Also create a callback function that will be handling the output given by the server.

Now to fill do_request:

do_request: function() {
	$.post(notification.request_url, {},
	function(data) {
		if (typeof(data.updates) != 'undefined') {
			$("#notify").html(data.updates);
		}
		notification.do_request();
	}, "json");
}

It requests the file given in the URL. Waits for it. Looks if there are updates in the answer and then call the function again (recursive loop.)

That was all the frontend code there is. Pretty small don’t you think? That’s why we are going to put all the logic in the backend.

The backend:

To make the backend work I created a small (not that great) update condition: if a certain file on the server contains text; output it and empty the file again.

Your updates would probably be stored in a database and marked if the user has received them, but that’s up to you. I’ll use this simple case to show you a quick result.

Create two files in the “notification” folder: “notification_request.php” and “updates.txt”. Also make “updates.txt” chmod 777 so PHP can edit that file.

The PHP script has to do the following:

  • Determine the time the script can be put on hold.
  • Constantly check if there are changes. If there are any, output the result.
  • Wait a short while and check again. If the max time as been reach output an empty result.

The basic code will look like this:

<?php

	//determine the starting time and the max execution time

	//set default response

	while(/* max time has not been reached */) {

		//check and determine update

		//if update is available; output and break script

		//if not: wait a little and clear the output
	}

	//output the default result if there is no update

?>

To determine the maximum execution time of a PHP script you can get this information from the PHP settings using ini_get, which can get a lot of information found in phpinfo().

The first part of the script would look like this:

//determine the starting time and the max timeout
$start_time = time();
$max_timeout = ini_get('max_execution_time');

//set default data
$data = array();

It determines the start time of the request and the maximum time PHP can put the script on hold. Also the default ouput is set (an empty array.)

Next part contains a bit more code:

//go into the loop
while((time() - $start_time) < $max_timeout) {

	//set the updates available to false
	$update_available = false;

	//open the file and get its contents
	$updates = file_get_contents("updates.txt");

	//if there is any content, put it in the output
	if (strlen($updates) > 0) {
		//set update available
		$update_available = true;

		//set updates
		$data['updates'] = $updates;

		//empty file
		file_put_contents("updates.txt", "");
	}

	//if there was an update output it and exit the script
	if ($update_available) {
		echo json_encode($data);
		exit();
	}

	//go into sleep for a little while and try again
	sleep(1);
	flush();
}

//if there are no updates within the set time: echo the empty result
echo json_encode($data);

Simply put, this script will return an update once the the file on the server (“updates.txt”) has contents and gives this to the frontend.
If there is no update, it will give the frontend an empty response and the script will do the same request again.

The frontend script will output the contents of the file once it has been changed on the server, almost instantaneously!

The following clip will show you this functionality:

Future:

Now it’s time to customize the script to meet your needs, not reading a file on the server, but rather getting updates from your database and creating a better output on the frontend side.

I didn’t make this too fancy because I only wanted to show you another approach to the problem of pushing notifications to the frontend.
This example would work perfectly in cooperation with sNotify, which I made a while ago.

If you have any ideas, suggestions and like to discuss this solution, please comment below.

I hope this helped you in developing an application with notifications and made you look at updating information in another way.

Articles like this one

If you liked this article you can add this post to:


 

10 Comments

  1. Marco said: October 21, 2009 at 8:34 am | Permalink

    Sweet – very smart thinking here. Looks a lot like the “Chat Box” post that Chris Coyier (CSS-Tricks) placed online a couple of days ago.

    I think there’s one catch though – since users never disconnect with your server, a DDOS might be an issue.

    Great work!


  2. Gaya said: October 21, 2009 at 9:35 am | Permalink

    Thanks for the comment Marco!

    About never disconnecting: the connection is refreshed every time the max_execution_time has been passed.

    But if the user would load a lot of requests at the same time, it would probably break indeed. That’s where you can make sure only 1 connection is available per user.

    Anyways: lots of possibilities: so little time ;)


  3. Yoosuf said: October 27, 2009 at 8:48 am | Permalink

    woow, its really nice work, appreciate it, nice thought! ultimatly u are using jQuery.

    nice work


  4. Yoosuf said: October 27, 2009 at 5:30 pm | Permalink

    just watch the video, awesome work buddy


  5. Gaya said: October 27, 2009 at 6:03 pm | Permalink

    Thanks for the comments Yoosuf! Hope this will help you in the future :)


  6. Drew said: November 2, 2009 at 10:12 pm | Permalink

    This is awesome work Gaya, but I wouldn’t expect less from you, keep it up!


  7. Gaya said: November 3, 2009 at 10:52 am | Permalink

    Thanks for the comment Drew! Stay tuned for more madness ;)


  8. Rynus_Rein said: December 13, 2009 at 11:27 pm | Permalink

    A rather interesting approach for implementing message pushing but think I wouldn’t go this way. Imaging each message pushing ‘line’ using 1 connection, blocking it for 30 (max_execution_time is 30 by default right?) seconds. With a single-threaded webserver it’d mean that the webserver doesn’t serve any other requests for 30 seconds.
    In a multi-threaded environment, any website with a moderate amount of concurrent users would probably be rendered unresponsive (as your webserver of choice probably has defined a max. number of connections) or in the worst case your server runs out of memory (because of all the client connections).
    As I said, an interesting approach but probably not my tool of choice :-)

    Correct me if I’m wrong though.


  9. Gaya said: December 14, 2009 at 9:22 am | Permalink

    Hi Rein,

    The stuff you’ve said could cause some problems indeed. I have no clue if single treaded servers still exist, if this is so: why? haha. I mean, only being able to handle a single request sucks. I really hope that sleep doesn’t interfere, if this is so: then this approach should not be used.
    I have no idea what this script would do if a lot of different requests are being made, should test it out!

    Thanks for the long comment Rein!


  10. AlexD said: January 23, 2010 at 5:13 am | Permalink

    I’d use the ape-server to push it :)


Leave a Comment

Your email is never shared. Get your own avatar with gravatar! Required fields are marked *

*

*