105

NodeJSall Levels

Embed Size (px)

DESCRIPTION

Node JS

Citation preview

Page 1: NodeJSall Levels
Page 2: NodeJSall Levels

I N T R O T O N O D E . J S- L E V E L O N E -

Page 3: NodeJSall Levels

INTRO TO NODE.JS

WHAT IS NODE.JS?

It’s fast because it’s mostly C code

Allows you to build scalable network applications using JavaScript on the server-side.

V8 JavaScript Runtime

Node.js

Page 4: NodeJSall Levels

INTRO TO NODE.JS

WHAT COULD YOU BUILD?• Websocket Server• Fast File Upload Client• Ad Server• Any Real-Time Data Apps

Like a chat server

Page 5: NodeJSall Levels

INTRO TO NODE.JS

WHAT IS NODE.JS NOT ?• A Web Framework• For Beginners It’s very low level• Multi-threaded

You can think of it as a single threaded server

Page 6: NodeJSall Levels

INTRO TO NODE.JS

OBJECTIVE: PRINT FILE CONTENTS

This is a “Callback”

Read file from Filesystem, set equal to “contents”Print contents

• Blocking Code

• Non-Blocking Code

Do something else

Read file from Filesystemwhenever you’re complete, print the contents

Do Something else

Page 7: NodeJSall Levels

console.log(contents);

INTRO TO NODE.JS

BLOCKING VS NON-BLOCKING

var contents = fs.readFileSync('/etc/hosts');console.log(contents);

console.log('Doing something else');

• Blocking Code

• Non-Blocking Code

console.log('Doing something else');Stop process until

complete

fs.readFile('/etc/hosts', function(err, contents) {

});

Page 8: NodeJSall Levels

fs.readFile('/etc/hosts', function(err, contents) {console.log(contents);

});

INTRO TO NODE.JS

CALLBACK ALTERNATE SYNTAX

var callback = function(err, contents) { console.log(contents);}

fs.readFile('/etc/hosts', callback);

Same as

Page 9: NodeJSall Levels

INTRO TO NODE.JS

BLOCKING VS NON-BLOCKING

blocking

0snon-blocking

10s5s

0s 10s5s

fs.readFile('/etc/hosts', callback);fs.readFile('/etc/inetcfg', callback);

var callback = function(err, contents) { console.log(contents);}

Page 10: NodeJSall Levels

hello.js

NODE.JS HELLO DOG

$ curl http://localhost:8080

Hello, this is dog.

How we require modules

Status code in headerResponse body

Close the connectionListen for connections on this port

$ node hello.js Run the server

var http = require('http');

http.createServer(function(request, response) {response.writeHead(200);response.write("Hello, this is dog.");response.end();

}).listen(8080, function(){console.log('Listening on port 8080...');

Listening on port 8080...

});

Page 11: NodeJSall Levels

THE EVENT LOOPvar http = require('http');http.createServer(function(request, response) {

}).listen(8080, function(){ console.log('Listening on port 8080...');

Starts the Event Loop when finished

...

Known Eventsrequest

Checking for

Events

Run the Callback});

Page 12: NodeJSall Levels

INTRO TO NODE.JS

WHY JAVASCRIPT ?“JavaScript has certain characteristics that make it very different than other dynamic languages, namely that it has no concept of threads. Its model of concurrency is completely based around events.”

- Ryan Dahl

Page 13: NodeJSall Levels

THE EVENT LOOPKnown Events

requestChecking for

Eventsconnection

close

Event Queue

closerequest

Events processed one at a time

Page 14: NodeJSall Levels

INTRO TO NODE.JS

WITH LONG RUNNING PROCESS

Represent long running process

var http = require('http');

http.createServer(function(request, response) {

}).listen(8080);

response.writeHead(200);

response.write("Dog is done.");response.end();

setTimeout(function(){

}, 5000); 5000ms = 5 seconds

response.write("Dog is running.");

Page 15: NodeJSall Levels

INTRO TO NODE.JS

TWO CALLBACKS HEREvar http = require('http');

http.createServer(function(request, response) {response.writeHead(200);

request

timeout

}).listen(8080);

response.write("Dog is done.");response.end();

setTimeout(function(){

}, 5000);

response.write("Dog is running.");

Page 16: NodeJSall Levels

TWO CALLBACKS TIMELINE

0s 10s5s

Request comes in, triggers request event

Request Callback executessetTimeout registered

Request comes in, triggers request event

Request Callback executessetTimeout registered

triggers setTimeout eventsetTimeout Callback executes

triggers setTimeout eventsetTimeout Callback

request

timeout

Page 17: NodeJSall Levels

WITH BLOCKING TIMELINE

0s 10s5s

Request comes in, triggers request event Request Callback executes

setTimeout executed

Request comes in, waits for server

Request comes in

triggers setTimeout eventsetTimeout Callback executedWasted Time

Request Callback executes

Page 18: NodeJSall Levels

INTRO TO NODE.JS

• Calls out to web services

TYPICAL BLOCKING THINGS

• Reads/Writes on the Database• Calls to extensions

Page 19: NodeJSall Levels

E V E N T S- L E V E L T W O -

Page 20: NodeJSall Levels

E V E N T S

EVENTS IN THE DOM

The DOM

The DOM triggers Events

click

events

you can listen for those events

submit

hover

When ‘click’ event is triggered!

attach

$("p").on("click", function(){ ... });

Page 21: NodeJSall Levels

E V E N T S

EVENTS IN NODE

EventEmitter

Many objects in Node emit events

net.Serverrequestevent

EventEmitterfs.readStream

dataevent

Page 22: NodeJSall Levels

E V E N T S

CUSTOM EVENT EMITTERS

var logger = new EventEmitter();

logger.emit('error', 'Spilled Milk');

ERR: Spilled Milk

logger.emit('error', 'Eggs Cracked');

var EventEmitter = require('events').EventEmitter;

error warn info

listen for error eventlogger.on('error', function(message){

console.log('ERR: ' + message);});

ERR: Eggs Cracked

events

Page 23: NodeJSall Levels

E V E N T S

EVENTS IN NODE

EventEmitter

Many objects in Node emit eventsnet.Server

requestevent

When ‘request’ event is emitted!function(request, response){ .. }

emit

attach

Page 24: NodeJSall Levels

E V E N T S

HTTP ECHO SERVER!http.createServer(function(request, response){ ... });

But what is really going on here?http://nodejs.org/api/

Page 25: NodeJSall Levels

E V E N T S

BREAKING IT DOWN!http.createServer(function(request, response){ ... });

Page 26: NodeJSall Levels

!http.createServer(function(request, response){ ... });

E V E N T S

ALTERNATE SYNTAX

!var server = http.createServer();function(request, response){ ... });server.on('request',

This is how we

Same as

function(){ ... });server.on('close',

add event listeners

Page 27: NodeJSall Levels

S T R E A M S- L E V E L T H R E E -

Page 28: NodeJSall Levels

S T R E A M S

WHAT ARE STREAMS?

Start ProcessingImmediately

Streams can be readable, writeable, or both

The API described here is for streams in Node version v0.10.x a.k.a. streams2

Page 29: NodeJSall Levels

S T R E A M S

STREAMING RESPONSE

Our browser receives "Dog is running."

"Dog is done."

(5 seconds later)

http.createServer(function(request, response) {

}).listen(8080);

response.writeHead(200);

response.write("<p>Dog is done.</p>");response.end();

setTimeout(function(){

}, 5000);

response.write("<p>Dog is running.</p>");

readable stream writable stream

Page 30: NodeJSall Levels

var chunk = null;while (null !== (chunk = request.read())) {!}

HOW TO READ FROM THE REQUEST ?

http.createServer(function(request, response) {

request.on('readable', function() {

});

response.end();

}).listen(8080)

request.on('end', function() {

});

response.writeHead(200);

(chunk.toString());console.log

EventEmitterReadable Stream readable

eventsemit

end

Let’s print what we receive from the request.

Page 31: NodeJSall Levels

HOW TO READ FROM THE REQUEST ?http.createServer(function(request, response) {

request.on('readable', function() {

});

response.end();

}).listen(8080)

request.on('end', function() {

});

response.writeHead(200);

response.write(chunk); request.pipe(response);

var chunk = null;while (null !== (chunk = request.read())) {!}

Page 32: NodeJSall Levels

S T R E A M S

LET’S CREATE AN ECHO SERVER!http.createServer(function(request, response) {

}).listen(8080)request.pipe(response);response.writeHead(200);

$ curl -d 'hello' http://localhost:8080

Hello on client

cat 'bleh.txt' | grep 'something'Kinda like on the command line

Page 33: NodeJSall Levels

S T R E A M S

DOCUMENTATION http://nodejs.org/api/

Stability Scores

Page 34: NodeJSall Levels

S T R E A M S

READING AND WRITING A FILEvar fs = require('fs');

var file = fs.createReadStream("readme.md");var newFile = fs.createWriteStream("readme_copy.md");

require filesystem module

file.pipe(newFile);

http://gulpjs.com/Build system built on top of Streams

Page 35: NodeJSall Levels

S T R E A M S

UPLOAD A FILE

var http = require('http');

http.createServer(function(request, response) {

request.pipe(newFile);

}).listen(8080);

response.end('uploaded!');request.on('end', function() {

});

var fs = require('fs');

var newFile = fs.createWriteStream("readme_copy.md");

$ curl --upload-file readme.md http://localhost:8080

uploaded!

Page 36: NodeJSall Levels

THE AWESOME STREAMING

client storage

server

original filetransferred file

non-blocking

0s 10s5s

Page 37: NodeJSall Levels

S T R E A M S

FILE UPLOADING PROGRESS

Page 38: NodeJSall Levels

S T R E A M S

FILE UPLOADING PROGRESS$ curl --upload-file file.jpg http://localhost:8080

progress: 3%progress: 6%progress: 9%progress: 12%progress: 13%...progress: 99%progress: 100%

Outputs:

• HTTP Server • File SystemWe’re going to need:

Page 39: NodeJSall Levels

S T R E A M S

REMEMBER THIS CODE?var fs = require('fs');

var newFile = fs.createWriteStream("readme_copy.md");

var http = require('http');

http.createServer(function(request, response) {

request.pipe(newFile);

}).listen(8080);

response.end('uploaded!');request.on('end', function() {

});

Page 40: NodeJSall Levels

S T R E A M S

REMEMBER THIS CODE?http.createServer(function(request, response) {

}).listen(8080);

...

uploadedBytes += chunk.length;var progress = (uploadedBytes / fileBytes) * 100;response.write("progress: " + parseInt(progress, 10) + "%\n");

var uploadedBytes = 0;var fileBytes = request.headers['content-length'];

request.on('readable', function() {

});

request.pipe(newFile);

while(null !== (chunk = request.read())){

}

var chunk = null;

var newFile = fs.createWriteStream("readme_copy.md");

Page 41: NodeJSall Levels

S T R E A M S

SHOWING PROGRESS

Page 42: NodeJSall Levels

M O D U L E S- L E V E L F O U R -

Page 43: NodeJSall Levels

M O D U L E S

REQUIRING MODULEShttp.js

How does it find these files?

var http = require('http');

var fs = require('fs'); fs.js

How does ‘require’ return the libraries?

Page 44: NodeJSall Levels

M O D U L E S

LET’S CREATE OUR OWN MODULE

custom_hello.js

custom_goodbye.js

app.js

module.exports = hello;

var hello = require('./custom_hello');

hello();

exports defines what require returns

var hello = function() { console.log("hello!");}

exports.goodbye = function() { console.log("bye!");}

var gb = require('./custom_goodbye');

gb.goodbye();

require('./custom_goodbye').goodbye(); If we only need to call once

Page 45: NodeJSall Levels

M O D U L E S

EXPORT MULTIPLE FUNCTIONS

my_module.js

app.js

var foo = function() { ... }var bar = function() { ... }

exports.foo = fooexports.bar = bar

var myMod = require('./my_module');myMod.foo();myMod.bar();

my_module.js

foo

bar

var baz = function() { ... }baz

“private”

Page 46: NodeJSall Levels

M O D U L E S

MAKING HTTP REQUESTSapp.js

logs response body

begins request

var http = require('http');

var options = { host: 'localhost', port: 8080, path: '/', method: 'POST' }

var request = http.request(options, function(response){response.on('data', function(data){console.log(data);

});});

request.end();request.write(message);

finishes request

var message = "Here's looking at you, kid.";

Page 47: NodeJSall Levels

M O D U L E S

ENCAPSULATING THE FUNCTIONapp.jsvar http = require('http');

var makeRequest = function(message) { var options = { host: 'localhost', port: 8080, path: '/', method: 'POST' }

var request = http.request(options, function(response){response.on('data', function(data){console.log(data);

});});

request.end();}

makeRequest("Here's looking at you, kid.");

request.write(message);

Text

Page 48: NodeJSall Levels

M O D U L E S

CREATING & USING A MODULEmake_request.jsvar http = require('http');

var makeRequest = function(message) {

}

module.exports = makeRequest;

...

app.jsvar makeRequest = require('./make_request');

makeRequest("Here's looking at you, kid");makeRequest("Hello, this is dog");

Where does require look for modules?

Page 49: NodeJSall Levels

M O D U L E S

REQUIRE SEARCH

var make_request = require('make_request')

/Home/eric/my_app/app.js

• /Home/eric/my_app/node_modules/make_request.js

var make_request = require('./make_request')var make_request = require('../make_request')var make_request = require('/Users/eric/nodes/make_request')

• /Home/eric/node_modules/make_request.js• /Home/node_modules/make_request.js• /node_modules/make_request.js

look in same directorylook in parent directory

Search in node_modules directories

However, all packages are directories

Page 50: NodeJSall Levels

M O D U L E S

NPM: THE USERLAND SEAPackage manager for node

• Comes with node• Module Repository• Dependency Management• Easily publish moduleshttp://npmjs.org

Page 51: NodeJSall Levels

M O D U L E S

INSTALLING A NPM MODULE

$ npm install request

In /Home/my_app

Home my_app reques node_modules

Installs into local node_modules directory

var request = require('request');

In /Home/my_app/app.js

Loads from local node_modules directory

Page 52: NodeJSall Levels

M O D U L E S

LOCAL VS GLOBAL

Global npm modules can’t be required

$ npm install coffee-script -g

Install modules with executables globally

$ coffee app.coffee

var coffee = require('coffee-script');

$ npm install coffee-script

var coffee = require('coffee-script');

global

Install them locally

Page 53: NodeJSall Levels

M O D U L E S

FINDING MODULESnpm registry

$ npm search request

npm command line

github search

Page 54: NodeJSall Levels

M O D U L E S

DEFINING YOUR DEPENDENCIESmy_app/package.json

version number

$ npm install

my_app connect node_modules

Installs into the node_modules directory

{"name": "My App","version": "1",

"dependencies": { "connect": "1.8.7" }}

Page 55: NodeJSall Levels

M O D U L E S

DEPENDENCIES

my_app connect node_modules

Installs sub-dependencies

connect node_modules qs

connect node_modules mime

connect node_modules formidable

"dependencies": { "connect": "1.8.7" }

my_app/package.json

Page 56: NodeJSall Levels

M O D U L E S

SEMANTIC VERSIONING"connect": "1.8.7" 1 8 7

Major Minor Patch. .

http://semver.org/ "connect": "~1.8.7" >=1.8.7 <1.9.0 Considered safe

"connect": "~1.8" >=1.8.0 <1.9.0 API could change

"connect": "~1" >=1.0.0 <2.0.0 DangerousRanges

Page 57: NodeJSall Levels

E X P R E S S- L E V E L F I V E -

Page 58: NodeJSall Levels

E X P R E S S

EXPRESS“Sinatra inspired web development framework for Node.js -- insanely fast, flexible, and simple”

• Easy route URLs to callbacks • Middleware (from Connect) • Environment based configuration • Redirection helpers • File Uploads

Page 59: NodeJSall Levels

E X P R E S S

$ npm install --save expressvar express = require('express');

var app = express();

app.get('/', function(request, response) { response.sendFile(__dirname + "/index.html");});

app.listen(8080);

$ curl http://localhost:8080/> 200 OK

root route

current directory

Installs the module and adds to package.json

Page 60: NodeJSall Levels

E X P R E S S

INTRODUCING EXPRESS

Page 61: NodeJSall Levels

E X P R E S S

EXPRESS ROUTESapp.js

route definition

get the last 10 tweets for screen_name

pipe the request to response

var request = require('request');var url = require('url');

app.get('/tweets/:username', function(req, response) {

var username = req.params.username;

options = { protocol: "http:", host: 'api.twitter.com', pathname: '/1/statuses/user_timeline.json', query: { screen_name: username, count: 10} }

var twitterUrl = url.format(options); request(twitterUrl).pipe(response);});

Page 62: NodeJSall Levels

E X P R E S S

EXPRESS ROUTES

Page 63: NodeJSall Levels

E X P R E S S

EXPRESS + HTML

Page 64: NodeJSall Levels

E X P R E S S

EJS TEMPLATES

$ npm install --save ejs

/Home/eric/my_app/views

"dependencies": { "express": "4.9.6",

}

my_app/package.json

default directory

"ejs": "1.0.0" Installs the module and adds to package.json

Page 65: NodeJSall Levels

E X P R E S S

EXPRESS TEMPLATESapp.js

views/tweets.ejs

app.get('/tweets/:username', function(req, response) {...request(url, function(err, res, body) {var tweets = JSON.parse(body);

response.render('tweets.ejs'); });});

<h1>Tweets for @<%= name %></h1><ul> <% tweets.forEach(function(tweet){ %> <li><%= tweet.text %></li> <% }); %></ul>

response.locals = {tweets: tweets, name: username};

Page 66: NodeJSall Levels

E X P R E S S

EXPRESS TEMPLATES

Page 67: NodeJSall Levels

E X P R E S S

TEMPLATE LAYOUTS

Page 68: NodeJSall Levels

S O C K E T . I O- L E V E L S I X -

Page 69: NodeJSall Levels

S O C K E T. I O

CHATTR

Page 70: NodeJSall Levels

S O C K E T. I O

WEBSOCKETS

browser traditional serverTraditional request/response cycle

Page 71: NodeJSall Levels

Using duplexed websocket connection

S O C K E T. I O

WEBSOCKETS

browser socket.io

Page 72: NodeJSall Levels

SOCKET.IO FOR WEBSOCKETS

var express = require('express');var app = express();var server = require('http').createServer(app);

Abstracts websockets with fallbacks

io.on('connection', function(client) {

});console.log('Client connected...');

$ npm install --save socket.io

app.js

var io = require('socket.io')(server);

server.listen(8080);

app.get('/', function (req, res) { res.sendFile(__dirname + '/index.html');});

S O C K E T. I O

Page 73: NodeJSall Levels

SOCKET.IO FOR WEBSOCKETSsocket.io client connects to the server

<script src="/socket.io/socket.io.js"></script>

var socket = io.connect('http://localhost:8080');<script>

</script>

index.html

S O C K E T. I O

Page 74: NodeJSall Levels

S O C K E T. I O

SENDING MESSAGES TO CLIENTio.on('connection', function(client) {

});

console.log('Client connected...');

<script src="/socket.io/socket.io.js"></script>

var socket = io.connect('http://localhost:8080');<script>

</script>

app.js

index.html

client.emit('messages', { hello: 'world' });

socket.on('messages', function (data) {

});alert(data.hello);

emit the ‘messages’ event on the client

listen for ‘messages’ events

Page 75: NodeJSall Levels

S O C K E T. I O

CHATTR HELLO WORLD

Page 76: NodeJSall Levels

S O C K E T. I O

SENDING MESSAGES TO SERVERio.on('connection', function(client) {

});

var socket = io.connect('http://localhost:8080');<script>

</script>

app.js

index.html

client.on('messages', function (data) {

});console.log(data);

$('#chat_form').submit(function(e){var message = $('#chat_input').val();

socket.emit('messages', message);});

listen for ‘messages’ events

emit the ‘messages’ event on the server

Page 77: NodeJSall Levels

S O C K E T. I O

CHATTR HELLO WORLD

Page 78: NodeJSall Levels

S O C K E T. I O

BROADCASTING MESSAGES

clients

server

app.js!socket.broadcast.emit("message", 'Hello');

Page 79: NodeJSall Levels

S O C K E T. I O

BROADCASTING MESSAGESio.on('connection', function(client) {

});

<script>

</script>

app.js

index.html

client.on('messages', function (data) {

});

...

broadcast message to all other clients connectedclient.broadcast.emit("messages", data);

socket.on('messages', function(data) { insertMessage(data) });insert message into the chat

Page 80: NodeJSall Levels

S O C K E T. I O

BROADCASTING MESSAGES

Page 81: NodeJSall Levels

S O C K E T. I O

SAVING DATA ON THE SOCKETio.on('connection', function(client) {

});

var server = io.connect('http://localhost:8080');<script>

</script>

app.js

index.html

client.on('join', function(name) {client.nickname = name;

});set the nickname associated

with this client

server.on('connect', function(data) {$('#status').html('Connected to chattr');nickname = prompt("What is your nickname?");

server.emit('join', nickname);});

notify the server of the users nickname

Page 82: NodeJSall Levels

S O C K E T. I O

SAVING DATA ON THE CLIENTio.on('connection', function(client) {

});

app.jsclient.on('join', function(name) {

client.nickname = name;});

client.on('messages', function(data){

});

client.broadcast.emit("message", nickname + ": " + message);broadcast with the name and message

client.emit("messages", nickname + ": " + message);send the same message back to our client

set the nickname associated with this client

var nickname = client.nickname;get the nickname of this client before broadcasting message

Page 83: NodeJSall Levels

P E R S I S T I N G D A T A- L E V E L S E V E N -

Page 84: NodeJSall Levels

P E R S I S T I N G D A T A

RECENT MESSAGES

Page 85: NodeJSall Levels

});});

P E R S I S T I N G D A T A

RECENT MESSAGESio.sockets.on('connection', function(client) {client.on('join', function(name) {client.nickname = name;client.broadcast.emit("chat", name + " joined the chat");

});client.on("messages", function(message){client.broadcast.emit("messages", client.nickname + ": " + message);

app.js

client.emit("messages", client.nickname + ": " + message);

Page 86: NodeJSall Levels

});});

STORING MESSAGES

io.sockets.on('connection', function(client) {client.on("messages", function(message){

app.js

storeMessage(client.nickname, message);

var messages = []; store messages in arrayvar storeMessage = function(name, data){

messages.push({name: name, data: data});if (messages.length > 10) {

messages.shift();}

}

add message to end of array

if more than 10 messages long, remove the first one

when client sends a message call storeMessage

client.broadcast.emit("messages", client.nickname + ": " + message);client.emit("messages", client.nickname + ": " + message);

Page 87: NodeJSall Levels

P E R S I S T I N G D A T A

EMITTING MESSAGESio.sockets.on('connection', function(client) {

});

app.js

client.on('join', function(name) {

});

messages.forEach(function(message) { client.emit("messages", message.name + ": " + message.data); }); iterate through messages array

and emit a message on the connecting client for each one

...

Page 88: NodeJSall Levels

P E R S I S T I N G D A T A

RECENT MESSAGES

Page 89: NodeJSall Levels

P E R S I S T I N G D A T A

PERSISTING STORES• MongoDB • CouchDB • PostgreSQL • Memcached • Riak

All non-blocking!

Redis is a key-value store

Page 90: NodeJSall Levels

P E R S I S T I N G D A T A

REDIS DATA STRUCTURES

Strings SET, GET, APPEND, DECR, INCR...

Hashes HSET, HGET, HDEL, HGETALL...

Lists LPUSH, LREM, LTRIM, RPOP, LINSERT...

Sets SADD, SREM, SMOVE, SMEMBERS...

Sorted Sets ZADD, ZREM, ZSCORE, ZRANK...

data structure commands

Page 91: NodeJSall Levels

P E R S I S T I N G D A T A

REDIS COMMAND DOCUMENTATION

Page 92: NodeJSall Levels

P E R S I S T I N G D A T A

NODE REDIS

Page 93: NodeJSall Levels

client.get("message1", function(err, reply){ console.log(reply);});

P E R S I S T I N G D A T A

REDIS

key value

"hello, yes this is dog"

var redis = require('redis');var client = redis.createClient();

client.set("message1", "hello, yes this is dog");client.set("message2", "hello, no this is spider");

commands are non-blocking

$ npm install redis --save

Page 94: NodeJSall Levels

P E R S I S T I N G D A T A

REDIS LISTS: PUSHINGAdd a string to the “messages” list

"1"

var message = "Hello, no this is spider";client.lpush("messages", message, function(err, reply){ console.log(reply);}); "2"

replies with list length

Add another string to “messages”

var message = "Hello, this is dog";client.lpush("messages", message, function(err, reply){

console.log(reply);});

Page 95: NodeJSall Levels

P E R S I S T I N G D A T A

REDIS LISTS: RETRIEVINGUsing LPUSH & LTRIM

trim keeps first two strings and removes the rest

Retrieving from list client.lrange("messages", 0, -1, function(err, messages){

console.log(messages);})

["Hello, no this is spider", "Oh sorry, wrong number"]

replies with all strings in list

client.ltrim("messages", 0, 1);

var message = "Hello, this is dog";client.lpush("messages", message, function(err, reply){

});

Page 96: NodeJSall Levels

P E R S I S T I N G D A T A

CONVERTING MESSAGES TO REDIS

var storeMessage = function(name, data){messages.push({name: name, data: data});

if (messages.length > 10) { messages.shift(); }}

Let’s use the List data-structure

app.js

Page 97: NodeJSall Levels

P E R S I S T I N G D A T A

CONVERTING STOREMESSAGE

var storeMessage = function(name, data){

}

var redisClient = redis.createClient();

var message = JSON.stringify({name: name, data: data});

redisClient.lpush("messages", message, function(err, response) {redisClient.ltrim("messages", 0, 9);

});keeps newest 10 items

app.js

need to turn object into string to store in redis

Page 98: NodeJSall Levels

P E R S I S T I N G D A T A

OUTPUT FROM LISTclient.on('join', function(name) {

});

messages.forEach(function(message) {client.emit("messages", message.name + ": " + message.data);

});

app.js

Page 99: NodeJSall Levels

P E R S I S T I N G D A T A

OUTPUT FROM LIST

client.on('join', function(name) {

});

messages.forEach(function(message) {

client.emit("messages", message.name + ": " + message.data);

});

redisClient.lrange("messages", 0, -1, function(err, messages){messages = messages.reverse();

message = JSON.parse(message);

});

app.js

reverse so they are emitted in correct order

parse into JSON object

Page 100: NodeJSall Levels

P E R S I S T I N G D A T A

IN ACTION

Page 101: NodeJSall Levels

P E R S I S T I N G D A T A

CURRENT CHATTER LISTSets are lists of unique data

client.sadd("names", "Dog");client.sadd("names", "Spider");client.sadd("names", "Gregg");

client.srem("names", "Spider");

!client.smembers("names", function(err, names){ console.log(names);});

["Dog", "Gregg"]

reply with all members of set

add & remove members of the names set

Page 102: NodeJSall Levels

app.js

P E R S I S T I N G D A T A

ADDING CHATTERSclient.on('join', function(name){

client.broadcast.emit("add chatter", name); redisClient.sadd("chatters", name);});

notify other clients a chatter has joined

add name to chatters set

index.htmlsocket.on('add chatter', function(name) {

var chatter = $('<li>'+name+'</li>').data('name', name); $('#chatters').append(chatter);});

Page 103: NodeJSall Levels

P E R S I S T I N G D A T A

ADDING CHATTERS (CONT)client.on('join', function(name){client.broadcast.emit("add chatter", name);

redisClient.sadd("chatters", name);});

app.js

emit all the currently logged in chatters to the newly connected client

redisClient.smembers('names', function(err, names) { names.forEach(function(name){ client.emit('add chatter', name); });});

Page 104: NodeJSall Levels

P E R S I S T I N G D A T A

REMOVING CHATTERSclient.on('disconnect', function(name){ app.js

index.html

client.broadcast.emit("remove chatter", client.nickname); redisClient.srem("chatters", client.nickname;);});

remove chatter when they disconnect from server

server.on('remove chatter', function(name) { $('#chatters li[data-name=’+ name + ']').remove();});

Page 105: NodeJSall Levels

P E R S I S T I N G D A T A

WELCOME TO CHATTR