JS
-
LEV EL
O NE
WHAT IS NODE.JS?
Allows you to build scalable network
applications using JavaScript on the server-side.
Node.js
V8 JavaScript Runtime
e
d
o
c
C
ly
t
s
o
m
s
t
i
e
s
u
a
c
Its fast be
INTRO TO NODE.JS
INTRO TO NODE.JS
c hat server
INTRO TO NODE.JS
Blocking Code
Read file from Filesystem, set equal to contents
Print contents
Do something else
Non-Blocking Code
Read file from Filesystem
whenever youre complete, print the contents
Do Something else
This is a Callback
INTRO TO NODE.JS
BLOCKING VS NON-BLOCKING
Blocking Code
e
t
e
l
p
m
o
c
l
i
t
n
u
s
s
e
Stop proc
Non-Blocking Code
fs.readFile('/etc/hosts', function(err, contents) {
console.log(contents);
});
console.log('Doing something else');
INTRO TO NODE.JS
Same as
var callback = function(err, contents) {
console.log(contents);
}
fs.readFile('/etc/hosts', callback);
INTRO TO NODE.JS
BLOCKING VS NON-BLOCKING
var callback = function(err, contents) {
console.log(contents);
}
fs.readFile('/etc/hosts', callback);
fs.readFile('/etc/inetcfg', callback);
blocking
0s
non-blocking
5s
10s
0s
5s
10s
INTRO TO NODE.JS
http.createServer(function(request, response) {
$ curl http://localhost:8080
Hello, this is dog.
request
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
INTRO TO NODE.JS
Known Events
Checking
for
Events
request
connection
close
response.write("Dog is done.");
response.end();
}, 5000);
5000ms = 5 seconds
}).listen(8080);
INTRO TO NODE.JS
request
response.writeHead(200);
response.write("Dog is running.");
setTimeout(function(){
response.write("Dog is done.");
response.end();
}, 5000);
}).listen(8080);
INTRO TO NODE.JS
timeout
0s
5s
10s
Wasted Time
0s
5s
10s
INTRO TO NODE.JS
EVENTS
-
LE VE L
TWO
click
submit
attach
hover
$("p").on("click",
function(){ ... });
!
events
EVENTS IN NODE
Many objects in Node emit events
net.Server
EventEmitter
request
fs.readStream
EventEmitter
data
EVENTS
event
event
EVENTS
error
events
warn
info
EVENTS IN NODE
Many objects in Node emit events
net.Server
EventEmitter
emit
attach
function(request,
response){ .. }
!
request
event
EVENTS
BREAKING IT DOWN
http.createServer(function(request,
response){ ... });
!
EVENTS
ALTERNATE SYNTAX
http.createServer(function(request,
response){ ... });
!
Same as
This is how we
add event listeners
server.on('close', function(){ ... });
EVENTS
STREAM S
-
L EVEL
TH REE
STREAMING RESPONSE
readable stream
writable stream
http.createServer(function(request, response) {
response.writeHead(200);
response.write("<p>Dog is running.</p>");
setTimeout(function(){
response.write("<p>Dog is done.</p>");
response.end();
}, 5000);
}).listen(8080);
"Dog is running."
(5 seconds later)
"Dog is done."
STREAMS
emit
events
readable
end
on client
Kinda like on the command line
Hello
STREAMS
DOCUMENTATION http://nodejs.org/api/
Stability Scores
STREAMS
http://gulpjs.com/
UPLOAD A FILE
var fs = require('fs');
var http = require('http');
http.createServer(function(request, response) {
var newFile = fs.createWriteStream("readme_copy.md");
request.pipe(newFile);
request.on('end', function() {
response.end('uploaded!');
});
}).listen(8080);
STREAMS
client
storage
original file
transferred file
non-blocking
0s
5s
10s
STREAMS
Outputs:
progress:
progress:
progress:
progress:
progress:
...
progress:
progress:
3%
6%
9%
12%
13%
99%
100%
STREAMS
HTTP Server
File System
STREAMS
SHOWING PROGRESS
STREAMS
MOD UL ES
-
LEV EL
F OUR
REQUIRING MODULES
var http = require('http');
http.js
var fs = require('fs');
fs.js
MODULES
custom_goodbye.js
exports.goodbye = function() {
console.log("bye!");
}
module.exports = hello;
app.js
MODULES
my_module.js
foo
baz
bar
app.js
var myMod = require('./my_module');
myMod.foo();
myMod.bar();
MODULES
private
app.js
begins request
finishes request
request.write(message);
request.end();
MODULES
Text
request.write(message);
request.end();
}
makeRequest("Here's looking at you, kid.");
MODULES
make_request.js
app.js
REQUIRE SEARCH
look in same directory
look in parent directory
/Home/eric/my_app/app.js
/Home/eric/my_app/node_modules/make_request.js
/Home/eric/node_modules/make_request.js
/Home/node_modules/make_request.js
/node_modules/make_request.js
MODULES
http://npmjs.org
MODULES
my_app
node_modules
reques
In /Home/my_app/app.js
var request = require('request');
MODULES
LOCAL VS GLOBAL
Install modules with executables globally
$ npm install coffee-script -g
global
$ coffee app.coffee
MODULES
FINDING MODULES
npm registry
npm command line
$ npm search request
github search
MODULES
version number
}
$ npm install
MODULES
node_modules
connect
DEPENDENCIES
my_app/package.json
"dependencies": {
"connect": "1.8.7"
}
Installs sub-dependencies
my_app
node_modules
connect
connect
node_modules
qs
connect
node_modules
mime
connect
node_modules
formidable
MODULES
SEMANTIC VERSIONING
"connect": "1.8.7"
Ranges
Dangerous
"connect": "~1"
>=1.0.0 <2.0.0
"connect": "~1.8"
>=1.8.0 <1.9.0
"connect": "~1.8.7"
>=1.8.7 <1.9.0
Considered safe
http://semver.org/
MODULES
EXPRESS
-
L EVEL
FIVE
EXPRESS
Sinatra inspired web development framework for Node.js -insanely fast, flexible, and simple
EXPRESS
n
o
s
.j
e
g
a
k
c
a
p
o
t
s
d
d
a
d
n
a
le
u
d
o
m
e
h
Installs t
root route
app.get('/', function(request, response) {
response.sendFile(__dirname + "/index.html");
});
current directory
app.listen(8080);
$ curl http://localhost:8080/
> 200 OK
EXPRESS
INTRODUCING EXPRESS
EXPRESS
EXPRESS ROUTES
var request = require('request');
var url = require('url');
route definition
app.js
EXPRESS
EXPRESS ROUTES
EXPRESS
EXPRESS + HTML
EXPRESS
my_app/package.json
"dependencies": {
"express": "4.9.6",
"ejs": "1.0.0"
}
n
o
s
.j
e
g
a
k
c
a
p
o
t
s
d
d
a
d
n
a
le
u
d
o
m
e
h
t
Installs
/Home/eric/my_app/views
default directory
EXPRESS
EXPRESS TEMPLATES
app.get('/tweets/:username', function(req, response) {
...
request(url, function(err, res, body) {
var tweets = JSON.parse(body);
response.locals = {tweets: tweets, name: username};
response.render('tweets.ejs');
});
});
views/tweets.ejs
EXPRESS
app.js
EXPRESS TEMPLATES
EXPRESS
TEMPLATE LAYOUTS
EXPRESS
SOCKET.IO
-
L EVEL
S IX
CHATTR
S O C K E T. I O
WEBSOCKETS
browser
traditional server
Traditional request/response cycle
S O C K E T. I O
WEBSOCKETS
browser
socket.io
Using duplexed websocket connection
S O C K E T. I O
app.js
express = require('express');
app = express();
server = require('http').createServer(app);
io = require('socket.io')(server);
io.on('connection', function(client) {
console.log('Client connected...');
});
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
server.listen(8080);
S O C K E T. I O
index.html
<script>
S O C K E T. I O
io.on('connection', function(client) {
console.log('Client connected...');
<script src="/socket.io/socket.io.js"></script>
<script>
index.html
</script>
S O C K E T. I O
S O C K E T. I O
app.js
});
<script>
socket.emit('messages', message);
});
</script>
S O C K E T. I O
index.html
S O C K E T. I O
BROADCASTING MESSAGES
app.js
clients
!
socket.broadcast.emit("message", 'Hello');
server
S O C K E T. I O
BROADCASTING MESSAGES
io.on('connection', function(client) {
app.js
});
<script>
...
index.html
S O C K E T. I O
BROADCASTING MESSAGES
S O C K E T. I O
app.js
<script>
index.html
server.on('connect', function(data) {
$('#status').html('Connected to chattr');
nickname = prompt("What is your nickname?");
server.emit('join', nickname);
});
</script>
S O C K E T. I O
io.on('connection', function(client) {
client.on('join', function(name) {
client.nickname = name;
});
client.on('messages', function(data){
var nickname = client.nickname;
client.emit("messages", nickname +
});
});
S O C K E T. I O
LEV EL
S EVEN
RECENT MESSAGES
PERSISTING DATA
RECENT MESSAGES
app.js
io.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);
client.emit("messages", client.nickname +
": " + message);
});
});
PERSISTING DATA
STORING MESSAGES
var messages = [];
app.js
io.sockets.on('connection', function(client) {
client.on("messages", function(message){
client.broadcast.emit("messages", client.nickname +
": " + message);
client.emit("messages", client.nickname + ": " + message);
storeMessage(client.nickname, message);
});
});
EMITTING MESSAGES
io.sockets.on('connection', function(client) {
...
app.js
client.on('join', function(name) {
messages.forEach(function(message) {
client.emit("messages", message.name + ": " + message.data);
});
});
});
PERSISTING DATA
RECENT MESSAGES
PERSISTING DATA
PERSISTING STORES
MongoDB
CouchDB
PostgreSQL
Memcached
Riak
All non-blocking!
commands
Strings
Hashes
Lists
Sets
Sorted Sets
PERSISTING DATA
PERSISTING DATA
NODE REDIS
PERSISTING DATA
REDIS
$ npm install redis --save
var redis = require('redis');
var client = redis.createClient();
client.set("message1", "hello, yes this is dog");
client.set("message2", "hello, no this is spider");
key
value
PERSISTING DATA
PERSISTING DATA
PERSISTING DATA
app.js
CONVERTING STOREMESSAGE
app.js
PERSISTING DATA
client.on('join', function(name) {
messages.forEach(function(message) {
client.emit("messages", message.name + ": " + message.data);
});
});
PERSISTING DATA
client.on('join', function(name) {
messages.forEach(function(message) {
message = JSON.parse(message);
PERSISTING DATA
IN ACTION
PERSISTING DATA
PERSISTING DATA
ADDING CHATTERS
client.on('join', function(name){
app.js
index.html
PERSISTING DATA
app.js
redisClient.sadd("chatters", name);
});
PERSISTING DATA
REMOVING CHATTERS
app.js
client.on('disconnect', function(name){
index.html
PERSISTING DATA
WELCOME TO CHATTR
PERSISTING DATA