Pushing Data to the Browser
Now that data from Twitter is in a more digestible format, you can push this data out to connected browsers using Socket.IO and use some client-side JavaScript to display the tweets. This is similar to the patterns that you saw in Hours 12 and 13 where data is received by a Socket.IO server and then broadcast to connected clients. To use Socket.IO, it must first be added as a dependency in the package.json file:
{ "name":"socket.io-twitter-example", "version":"0.0.1", "private":true, "dependencies":{ "express":"2.5.4", "ntwitter":"0.2.10", "socket.io":"0.8.7" } }
Then, Socket.IO must be required in the main server file and instructed to listen to the Express server. This is exactly the same as the examples that you worked through in Hours 12 and 13:
var app = require('express').createServer(), twitter = require('ntwitter'), io = require('socket.IO').listen(app);
The streaming API request can now be augmented to push the data out to any connected Socket.IO clients whenever a new data event is received:
twit.stream('statuses/filter', { track: ['love', 'hate'] }, function(stream) { stream.on('data', function (data) { io.sockets.volatile.emit('tweet', { user: data.user.screen_name, text: data.text }); }); });
Instead of logging the data to the console, you are now doing something useful with the data by pushing it out to connected clients. A simple JSON structure is created to hold the name of the user and the tweet. If you want to send more information to the browser, you could simply extend the JSON object to hold other attributes.
You may have noticed that, instead of using io.sockets.emit as you did in Hours 12 and 13, you are now using io.sockets.volatile.emit. This is an additional method provided by Socket.IO for scenarios where certain messages can be dropped. This may be down to network issues or a user being in the middle of a request-response cycle. This is particularly the case where high volumes of messages are being sent to clients. By using the volatile method, you can ensure that your application will not suffer if a certain client does not receive a message. In other words, it does not matter whether a client does not receive a message.
The Express server is also instructed to serve a single HTML page so that the data can be viewed in a browser.
app.get('/', function (req, res) { res.sendfile(__dirname + '/index.html'); });
On the client side (or browser), some simple client-side JavaScript is added to the index.html file to listen for new tweets being sent to the browser and display them to the user. The full HTML file is available in the example that follows:
<ul class="tweets"></ul> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script src="/socket.io/socket.io.js"></script> <script> var socket = io.connect(); jQuery(function ($) { var tweetList = $('ul.tweets'); socket.on('tweet', function (data) { tweetList .prepend('<li>' + data.user + ': ' + data.text + '</li>'); }); }); </script>
An empty unordered list is added to the DOM (Document Object Model), and this is filled with a new list item containing the screen name of the user and the tweet each time a new tweet is received. This uses jQuery’s prepend() method to insert data received into a list item within the unordered list. This has the effect of creating a stream on the page.
Now, whenever Socket.IO pushes a new tweet event out the browser receives it and writes it to the page immediately. Instead of viewing the stream of tweets in a terminal, it can now be viewed in the browser!