SlideShare a Scribd company logo
verona
21/05/2011
gabriele lana
gabriele.lana@cleancode.it
  twitter: @gabrielelana
why
         node.js?

“Node's goal is to
  provide an easy
   way to build
scalable network
    programs”

              http://nodejs.org/#about
what is
                  node.js?
•   asynchronous i/o framework
•   core in c++ on top of v8
•   rest of it in javascript
•   swiss army knife for network
    related stuffs
•   can handle thousands of
    concurrent connections with
    minimal overhead (cpu/memory)
    on a single process
Single thread
synchronous I/0
Single thread
synchronous I/0
multiple thread
synchronous I/0
multiple thread
synchronous I/0
you can
  “always”
 scale with
  multiple
machines but
  it costs
  you $$$
Introduction to Nodejs
but...
what is HE
 doing?
CPU BOUND
          TASKS?


  but...
what is HE
 doing?
CPU BOUND
          TASKS?

             ...OR I/o
  but...       BOUND
what is HE    TASKS?
 doing?
synchronous I/0

function productsInCart(request, response) {
    var db = new Db()
    var user = new User(request)
    if (user.isAuthorized("cart/products")) {
        response.write(
             JSON.stringify(
                 db.productsInCart(user.cartId())
             )
        )
    } else {
        response.unauthorized()
    }
}
synchronous I/0

function productsInCart(request, response) {
    var db = new Db()
    var user = new User(request)
    if (user.isAuthorized("cart/products")) {
        response.write(
             JSON.stringify(
                 db.productsInCart(user.cartId())
             )
        )
    } else {
        response.unauthorized()
    }
}
synchronous I/0

function productsInCart(request, response) {
    var db = new Db()
    var user = new User(request)
    if (user.isAuthorized("cart/products")) {
        response.write(
             JSON.stringify(
                 db.productsInCart(user.cartId())
             )
        )
    } else {
        response.unauthorized()
    }
}
synchronous I/0

function productsInCart(request, response) {
    var db = new Db()
    var user = new User(request)
    if (user.isAuthorized("cart/products")) {
        response.write(
             JSON.stringify(
                 db.productsInCart(user.cartId())
             )
        )
    } else {
        response.unauthorized()
    }
}
single thread
asynchronous I/0
single thread
asynchronous I/0


           I am
       “callback”
         call me
         if you
        need me...
hello_world_server.js
                                          Event Emitter

                        var http = require("http")

                        var server = http.createServer(function(request, response) {
                           response.writeHead(200, {
                              "Content-Type": "plain/text"
                           })
                           response.write("Hello Worldn")
                           response.end()
                        })

                        server.listen(8080)

                        console.log("> SERVER STARTED")
hello_world_server.js
                                          Event Emitter

                        var http = require("http")

                        var server = http.createServer(function(request, response) {
                           response.writeHead(200, {
                              "Content-Type": "plain/text"
                           })
                           response.write("Hello Worldn")
                           response.end()
                        })

                        server.listen(8080)

                        console.log("> SERVER STARTED")
hello_world_server.js
                                          Event Emitter

                        var http = require("http")

                        var server = http.createServer(function(request, response) {
                           response.writeHead(200, {
                              "Content-Type": "plain/text"
                           })
                           response.write("Hello Worldn")
                           response.end()
                        })

                        server.listen(8080)

                        console.log("> SERVER STARTED")
hello_world_server.js
                                          Event Emitter

                        var http = require("http")

                        var server = http.createServer(function(request, response) {
                           response.writeHead(200, {
                              "Content-Type": "plain/text"
                           })
                           response.write("Hello Worldn")
                           response.end()
                        })

                        server.listen(8080)

                        console.log("> SERVER STARTED")
Event Emitter

coder@apollo:~/Work/src/node/examples$ node hello_world_server.js
> SERVER STARTED
                                                                    #1
coder@apollo:~$ curl "http://localhost:8080/"
Hello World
                                                                    #2
Event Emitter

                        var server = require("http").createServer()
hello_world_server.js



                        server.on("request", function(request, response) {
                           console.log("> REQUEST STARTED")
                           request.on("end", function() {
                              console.log("> REQUEST CLOSED")
                              response.writeHead(200, {
                                 "Content-Type": "plain/text"
                              })
                              response.end("Hello Worldn")
                              server.close()
                           })
                           response.on("close", function() {
                              console.log("> RESPONSE CLOSED")
                           })
                        })
hello_world_server.js
                                          Event Emitter


                        ...

                        server.on("close", function() {
                           console.log("> SERVER CLOSED")
                        })

                        server.on("listening", function() {
                           console.log("> SERVER STARTED")
                        })

                        server.listen(8080)
Event Emitter

coder@apollo:~/Work/src/node/examples$ node hello_world_server.js
> SERVER STARTED                                                    #1
coder@apollo:~$ curl "http://localhost:8080/"
Hello World                                                         #2
                                                                    #1
> REQUEST STARTED
> REQUEST CLOSED
> SERVER CLOSED
why so
complicated?
data streamS
                  server.on("request", function(request, response) {
                    var chunks = [],
                        output = fs.createWriteStream("./output")
proxy_stream.js




                       request.on("data", function(chunk) {
                          chunks = forEachLine(chunks.concat(chunk), function(line) {
                             output.write(parseInt(line, 10) * 2)
                             output.write("n")
                          })
                       })

                       request.on("end", function() {
                          response.writeHead(200, { "Content-Type": "plain/text" })
                          response.end("OKn")
                          output.end()
                          server.close()
                       })
                  })
data streamS

coder@apollo:~/Work/src/node/examples$ node stream_doubler.js
                                                                    #1
coder@apollo:~$ curl "http://localhost:8080/" --data $'1n2n3n'
OK                                                                  #2
coder@apollo:~/Work/src/node/examples$ cat output
2
4
6                                                                   #1
why
                 javascript?


•   Friendly callbacks
•   ubiquitous (well known)
•   no I/o primitives
•   one language to rule them all
web applications
                             before: a web
mind shift #1               server with some
                            application logic


                        application
           Web server

                        application


                        application


                        application
web applications
                        after: an application
mind shift #1             accessible over
                                http
        web server




                     application
web applications
                        after: an application
mind shift #1                 that can
                          communicate and
                         collaborate with
                             the world
        web server




                     application
web applications
                    before: stateful
mind shift #2   • no easy to scale
                • no easy to reuse

                v
                     M
                c
web applications
                    before: stateful
mind shift #2   • no easy to scale
                • no easy to reuse

                v
                     M
                c


  conversation       application
     state             state
web applications
                    before: stateful
mind shift #2   • no easy to scale
                • no easy to reuse

                v
                     M
                c



   tightly coupled
web applications
                    after: stateless
mind shift #2      • easy to scale
                   • easy to reuse


       v
            http
                       M
       c
web applications
                    after: stateless
mind shift #2      • easy to scale
                   • easy to reuse


       v
            http
                       M
       c


conversation       application
   state             state
web applications
                       after: stateless
mind shift #2
                http




                       web server
                                        M
                http

                                     statefull
                                    connection



• easy to scale                                  M
• easy to reuse
no fluff
just stuff
What about
cpu bound
  tasks?
the fork
long_running_job.sh                          be with you



                      #!/bin/bash

                      for count in `seq 1 100`; do
                           echo $count
                           sleep 0.1
                      done
the fork
long_running_server.js                              be with you
                         var spawn = require("child_process").spawn,
                             server = require("http").createServer()

                         server.on("request", function(request, response) {
                           var job = spawn("./long_running_job.sh")

                              job.stdout.on("data", function(tick) {
                                 response.write(tick)
                              })

                              job.on("exit", function() {
                                 response.end()
                              })
                         })
the fork
                                     be with you
coder@apollo:~$ ab -c 1 -n 1 "http://localhost:8080/"
...
Concurrency Level:      1
Time taken for tests:   10.531 seconds
...


coder@apollo:~$ ab -c 1 -n 2 "http://localhost:8080/"
...
Concurrency Level:      1
Time taken for tests:   20.108 seconds
...
the fork
                                     be with you
coder@apollo:~$ ab -c 2 -n 1 "http://localhost:8080/"
...
Concurrency Level:      2
Time taken for tests:   10.634 seconds
...

coder@apollo:~$ ab -c 100 -n 100 "http://localhost:8080/"
...
Concurrency Level:      100
Time taken for tests:   11.198 seconds
...

coder@apollo:~$ ab -c 500 -n 500 "http://localhost:8080/"
...
Concurrency Level:      500
Time taken for tests:   31.082 seconds
...
enter comet

w
 at
   ch
watch          M                spawn
   ch
 at
w




               watch
           w




                       w
        t a




                       at
          ch




                           ch
enter comet




demo
INSTALL NPM
                                     (node packet manager)

coder@apollo:~/Work/src/node/examples$ curl http://npmjs.org/install.sh | sh
...
npm ok
It worked

coder@apollo:~/Work/src/node/examples$ npm search | wc -l
1918

coder@apollo:~/Work/src/node/examples$ npm install connect socket.io underscore
coder@apollo:~/Work/src/node/examples$ npm list
!"# connect@1.4.1
$ !"" mime@1.2.2
$ %"" qs@0.1.0
%"" socket.io@0.6.17
%"" underscore@1.1.6
server/
                                                      routing
progress_server.js




                     var server = connect(
                       connect.favicon(),
                       connect.logger({"buffer": true}),
                       connect.router(function(resource) {
                         resource.post("/spawn", function(request, response) {
                            ...
                         })
                       }),
                       connect.static(path.join(__dirname, "public"), {"cache": true})
                     )
server/
                                                       routing
progress_server.js



                     resource.post("/spawn", function(request, response) {
                       var job = spawn(path.join(__dirname, "bin", "job.sh")),
                           id = ++counter

                          response.writeHead(202, {"Content-Type": "plain/text"})
                          response.end("OKn")

                          job.stdout.on("data", function(output) {
                             var progress = parseInt(output.toString(), 10)
                             _(connections).each(function(connection) {
                                connection.send({"id": id, "progress": progress})
                             })
                          })
                     })
server/
                                                   socket.io
progress_server.js




                     io.listen(server).on("connection", function(client) {

                          connections[client.sessionId] = client

                          client.on("disconnect", function() {
                             delete connections[client.sessionId]
                          })

                     })
server/
                                                       simulation
progress_server.js



                     server.listen(port, host, function() {
                       var spawnJobsInterval = setInterval(function() {
                         http.request({
                           "port": port, "host": host, "method": "POST", "path": "/spawn"
                         }).end()
                       }, Math.floor(Math.random()*2000)+500)

                          server.on("close", function() {
                             clearInterval(spawnJobsInterval)
                             process.exit()
                          })
                     })

                     process.on("SIGINT", function() {
                        server.close()
                     })
interface/html
             <html>
               <head>
                 <title>Node.js - Long Running Jobs</title>
                 <link href="css/style.css" rel="stylesheet" />
                 <script type="text/javascript" src="/socket.io/socket.io.js"></script>
                 <script type="text/javascript" src="js/jquery-1.6.0.js"></script>
                 <script type="text/javascript" src="js/progress.js"></script>
index.html




               </head>
               <body>
                 <div id="template">
                    <div class="progress-container">
                      <span class="progress-text">JOB/? - ?%</span>
                      <div class="progress-bar"></div>
                    </div>
                 </div>
                 <div id="container"> </div>
               </body>
               <script>
                 ...
               </script>
             </html>
interface/
                                            socket.io
             <html>
               ...
               <script>
                 $(function() {
                    var socket = new io.Socket()
index.html




                   socket.on("connect", function() { })
                   socket.on("disconnect", function() { })
                   socket.on("message", function(job) {
                      $("#template").progressBar(job.id, job.progress)
                   })

                   socket.connect()
                 })
               </script>
             </html>
interface/
                                          progress bar
              $.fn.progressBar = function(id, progress) {
                var $template = $(this)
                $("#job-" + id)
                  .otherwise(function() {
                     return $template.children().clone()
progress.js




                       .attr("id", "job-" + id)
                       .find(".progress-text").text("JOB/" + id + " - 0%").end()
                       .appendTo("#container")
                  })
                  .find(".progress-text").text("JOB/" + id + " - " + progress + "%").end()
                  .find(".progress-bar").css("width", progress + "%").end()
                  .tap(function() {
                     if (progress === 100) {
                       $(this)
                         .find(".progress-bar").css("background-color", "red").end()
                         .after(500, function() {
                            $(this).fadeOut("slow", function() {
                               $(this).remove()
                            })
                         })
                     }
interface/
                                       progress bar
              $.fn.otherwise = function(ifNotFound) {
                if (this.length === 0) {
                  return ifNotFound()
                }
progress.js




                return this
              }

              $.fn.after = function(milliseconds, doSomething) {
                var self = this
                setTimeout(function() {
                  doSomething.apply(self)
                }, milliseconds)
                return this
              }

              $.fn.tap = function() {
                var fn = Array.prototype.shift.apply(arguments)
                fn.apply(this, arguments)
                return this
              }
we can do it
with a little
more “style”
server/
                                                   event emitter
                     var Job = (function() {
                       var EventEmitter = require("events").EventEmitter,
progress_server.js



                           spawn = require("child_process").spawn,
                           inherits = require("util").inherits

                       function Job(id) {
                         EventEmitter.call(this)
                         this.id = id
                       }

                       inherits(Job, EventEmitter)

                       Job.prototype.run = function() {
                          return _(this).tap(function(job) {
                             spawn(path.join(__dirname, "bin", "job.sh"))
                               .stdout.on("data", function(output) {
                                  job.emit("progress", job.id, parseInt(output.toString(), 10))
                               })
                          })
                       }
                       return Job
                     })()
server/
                                               event emitter
progress_server.js




                     resource.post("/spawn", function(request, response) {
                       new Job(++counter)
                         .on("progress", function(id, progress) {
                            _(connections).each(function(connection) {
                               connection.send({"id": id, "progress": progress})
                            })
                         })
                         .run()

                          response.writeHead(202, { "Content-Type": "plain/text" })
                          response.end("OKn")
                     })
node.js is
 awesome
 but when
 should i
  use it?
when to use it?

•   chat/messaging
•   real-time applications
•   intelligent proxies
•   high concurrency applications
•   communication hubs
•   coordinators
please tell
me something
 bad about
  node.js
some warnings
•   release stable 0.4.7 (young)
•   lots of stuffs to look at
•   lots of half backed stuffs
•   retro compatibility???
•   bad at handling static contents
•   Bad at handling binary contents
•   hard to find organized and
    authoritative informations
vs
Introduction to Nodejs
Introduction to Nodejs
Questions?
gabriele lana
   gabriele.lana@cleancode.it
     twitter: @gabrielelana

http://joind.in/3359

More Related Content

PDF
Node.js - A Quick Tour
KEY
Node.js - Best practices
KEY
Building a real life application in node js
PPTX
introduction to node.js
PDF
Building servers with Node.js
PPT
Building your first Node app with Connect & Express
KEY
A million connections and beyond - Node.js at scale
PDF
Nodejs - A quick tour (v6)
Node.js - A Quick Tour
Node.js - Best practices
Building a real life application in node js
introduction to node.js
Building servers with Node.js
Building your first Node app with Connect & Express
A million connections and beyond - Node.js at scale
Nodejs - A quick tour (v6)

What's hot (20)

KEY
Writing robust Node.js applications
PPTX
Building Web Apps with Express
PDF
Nodejs Explained with Examples
KEY
node.js: Javascript's in your backend
PDF
Express node js
PPT
Node js presentation
PDF
Node js introduction
PPTX
Express js
PDF
Beyond Phoenix
PDF
Web Crawling with NodeJS
PDF
Non-blocking I/O, Event loops and node.js
PPT
RESTful API In Node Js using Express
PDF
soft-shake.ch - Hands on Node.js
KEY
A language for the Internet: Why JavaScript and Node.js is right for Internet...
PDF
Using Node.js to Build Great Streaming Services - HTML5 Dev Conf
KEY
NodeJS
PDF
Comet with node.js and V8
PDF
What is nodejs
KEY
Introduction to node.js
PDF
Writing robust Node.js applications
Building Web Apps with Express
Nodejs Explained with Examples
node.js: Javascript's in your backend
Express node js
Node js presentation
Node js introduction
Express js
Beyond Phoenix
Web Crawling with NodeJS
Non-blocking I/O, Event loops and node.js
RESTful API In Node Js using Express
soft-shake.ch - Hands on Node.js
A language for the Internet: Why JavaScript and Node.js is right for Internet...
Using Node.js to Build Great Streaming Services - HTML5 Dev Conf
NodeJS
Comet with node.js and V8
What is nodejs
Introduction to node.js
Ad

Viewers also liked (6)

PPTX
Introduction to Node.js
PDF
Anatomy of a Modern Node.js Application Architecture
PDF
JavaScript and Node.js Fundamentals
PPTX
Nodejs intro
PDF
NodeJS for Beginner
PDF
Node Foundation Membership Overview 20160907
Introduction to Node.js
Anatomy of a Modern Node.js Application Architecture
JavaScript and Node.js Fundamentals
Nodejs intro
NodeJS for Beginner
Node Foundation Membership Overview 20160907
Ad

Similar to Introduction to Nodejs (20)

PDF
Nodejsexplained 101116115055-phpapp02
KEY
A language for the Internet: Why JavaScript and Node.js is right for Internet...
PPT
Play!ng with scala
PDF
Websockets talk at Rubyconf Uruguay 2010
PPT
Spring data iii
PDF
From Node to Go
PDF
NoSQL and JavaScript: a Love Story
PDF
Socket.IO
KEY
CouchDB on Android
PDF
Node.js - async for the rest of us.
PDF
XQuery Rocks
PDF
Server Side Swift: Vapor
PDF
Serverless Ballerina
PPTX
Bare-knuckle web development
PPTX
node.js workshop- node.js basics
PDF
Play vs Rails
PPT
JavaScript JQUERY AJAX
KEY
Using and scaling Rack and Rack-based middleware
PPTX
Introduction to Vert.x
PDF
Security Challenges in Node.js
Nodejsexplained 101116115055-phpapp02
A language for the Internet: Why JavaScript and Node.js is right for Internet...
Play!ng with scala
Websockets talk at Rubyconf Uruguay 2010
Spring data iii
From Node to Go
NoSQL and JavaScript: a Love Story
Socket.IO
CouchDB on Android
Node.js - async for the rest of us.
XQuery Rocks
Server Side Swift: Vapor
Serverless Ballerina
Bare-knuckle web development
node.js workshop- node.js basics
Play vs Rails
JavaScript JQUERY AJAX
Using and scaling Rack and Rack-based middleware
Introduction to Vert.x
Security Challenges in Node.js

More from Gabriele Lana (20)

PDF
Microservice Architectures
PDF
Professional Programmer 2018
PDF
Parse Everything With Elixir
PDF
The Magic Of Elixir
PDF
Professional Programmer (3 Years Later)
PDF
Resource Oriented Design
PDF
Agileday Coderetreat 2013
PDF
Milano Legacy Coderetreat 2013
PDF
Minimum Viable Product
PDF
API Over HTTP
PDF
coderetreat
PDF
Professional Programmer
PDF
It is not supposed to fly but it does
PDF
MongoDB With Style
PDF
PDF
Magic of Ruby
PDF
Why couchdb is cool
PDF
ProgrammingKatas
PDF
CouchDB Vs MongoDB
PDF
Refactoring In Tdd The Missing Part
Microservice Architectures
Professional Programmer 2018
Parse Everything With Elixir
The Magic Of Elixir
Professional Programmer (3 Years Later)
Resource Oriented Design
Agileday Coderetreat 2013
Milano Legacy Coderetreat 2013
Minimum Viable Product
API Over HTTP
coderetreat
Professional Programmer
It is not supposed to fly but it does
MongoDB With Style
Magic of Ruby
Why couchdb is cool
ProgrammingKatas
CouchDB Vs MongoDB
Refactoring In Tdd The Missing Part

Recently uploaded (20)

PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
Approach and Philosophy of On baking technology
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Empathic Computing: Creating Shared Understanding
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
cuic standard and advanced reporting.pdf
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
PDF
Modernizing your data center with Dell and AMD
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Encapsulation theory and applications.pdf
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
Approach and Philosophy of On baking technology
The AUB Centre for AI in Media Proposal.docx
Network Security Unit 5.pdf for BCA BBA.
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Empathic Computing: Creating Shared Understanding
The Rise and Fall of 3GPP – Time for a Sabbatical?
cuic standard and advanced reporting.pdf
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Dropbox Q2 2025 Financial Results & Investor Presentation
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
Modernizing your data center with Dell and AMD
Unlocking AI with Model Context Protocol (MCP)
Encapsulation theory and applications.pdf
“AI and Expert System Decision Support & Business Intelligence Systems”
Digital-Transformation-Roadmap-for-Companies.pptx
Encapsulation_ Review paper, used for researhc scholars
Reach Out and Touch Someone: Haptics and Empathic Computing

Introduction to Nodejs

  • 3. why node.js? “Node's goal is to provide an easy way to build scalable network programs” http://nodejs.org/#about
  • 4. what is node.js? • asynchronous i/o framework • core in c++ on top of v8 • rest of it in javascript • swiss army knife for network related stuffs • can handle thousands of concurrent connections with minimal overhead (cpu/memory) on a single process
  • 9. you can “always” scale with multiple machines but it costs you $$$
  • 12. CPU BOUND TASKS? but... what is HE doing?
  • 13. CPU BOUND TASKS? ...OR I/o but... BOUND what is HE TASKS? doing?
  • 14. synchronous I/0 function productsInCart(request, response) { var db = new Db() var user = new User(request) if (user.isAuthorized("cart/products")) { response.write( JSON.stringify( db.productsInCart(user.cartId()) ) ) } else { response.unauthorized() } }
  • 15. synchronous I/0 function productsInCart(request, response) { var db = new Db() var user = new User(request) if (user.isAuthorized("cart/products")) { response.write( JSON.stringify( db.productsInCart(user.cartId()) ) ) } else { response.unauthorized() } }
  • 16. synchronous I/0 function productsInCart(request, response) { var db = new Db() var user = new User(request) if (user.isAuthorized("cart/products")) { response.write( JSON.stringify( db.productsInCart(user.cartId()) ) ) } else { response.unauthorized() } }
  • 17. synchronous I/0 function productsInCart(request, response) { var db = new Db() var user = new User(request) if (user.isAuthorized("cart/products")) { response.write( JSON.stringify( db.productsInCart(user.cartId()) ) ) } else { response.unauthorized() } }
  • 19. single thread asynchronous I/0 I am “callback” call me if you need me...
  • 20. hello_world_server.js Event Emitter var http = require("http") var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "plain/text" }) response.write("Hello Worldn") response.end() }) server.listen(8080) console.log("> SERVER STARTED")
  • 21. hello_world_server.js Event Emitter var http = require("http") var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "plain/text" }) response.write("Hello Worldn") response.end() }) server.listen(8080) console.log("> SERVER STARTED")
  • 22. hello_world_server.js Event Emitter var http = require("http") var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "plain/text" }) response.write("Hello Worldn") response.end() }) server.listen(8080) console.log("> SERVER STARTED")
  • 23. hello_world_server.js Event Emitter var http = require("http") var server = http.createServer(function(request, response) { response.writeHead(200, { "Content-Type": "plain/text" }) response.write("Hello Worldn") response.end() }) server.listen(8080) console.log("> SERVER STARTED")
  • 24. Event Emitter coder@apollo:~/Work/src/node/examples$ node hello_world_server.js > SERVER STARTED #1 coder@apollo:~$ curl "http://localhost:8080/" Hello World #2
  • 25. Event Emitter var server = require("http").createServer() hello_world_server.js server.on("request", function(request, response) { console.log("> REQUEST STARTED") request.on("end", function() { console.log("> REQUEST CLOSED") response.writeHead(200, { "Content-Type": "plain/text" }) response.end("Hello Worldn") server.close() }) response.on("close", function() { console.log("> RESPONSE CLOSED") }) })
  • 26. hello_world_server.js Event Emitter ... server.on("close", function() { console.log("> SERVER CLOSED") }) server.on("listening", function() { console.log("> SERVER STARTED") }) server.listen(8080)
  • 27. Event Emitter coder@apollo:~/Work/src/node/examples$ node hello_world_server.js > SERVER STARTED #1 coder@apollo:~$ curl "http://localhost:8080/" Hello World #2 #1 > REQUEST STARTED > REQUEST CLOSED > SERVER CLOSED
  • 29. data streamS server.on("request", function(request, response) { var chunks = [], output = fs.createWriteStream("./output") proxy_stream.js request.on("data", function(chunk) { chunks = forEachLine(chunks.concat(chunk), function(line) { output.write(parseInt(line, 10) * 2) output.write("n") }) }) request.on("end", function() { response.writeHead(200, { "Content-Type": "plain/text" }) response.end("OKn") output.end() server.close() }) })
  • 30. data streamS coder@apollo:~/Work/src/node/examples$ node stream_doubler.js #1 coder@apollo:~$ curl "http://localhost:8080/" --data $'1n2n3n' OK #2 coder@apollo:~/Work/src/node/examples$ cat output 2 4 6 #1
  • 31. why javascript? • Friendly callbacks • ubiquitous (well known) • no I/o primitives • one language to rule them all
  • 32. web applications before: a web mind shift #1 server with some application logic application Web server application application application
  • 33. web applications after: an application mind shift #1 accessible over http web server application
  • 34. web applications after: an application mind shift #1 that can communicate and collaborate with the world web server application
  • 35. web applications before: stateful mind shift #2 • no easy to scale • no easy to reuse v M c
  • 36. web applications before: stateful mind shift #2 • no easy to scale • no easy to reuse v M c conversation application state state
  • 37. web applications before: stateful mind shift #2 • no easy to scale • no easy to reuse v M c tightly coupled
  • 38. web applications after: stateless mind shift #2 • easy to scale • easy to reuse v http M c
  • 39. web applications after: stateless mind shift #2 • easy to scale • easy to reuse v http M c conversation application state state
  • 40. web applications after: stateless mind shift #2 http web server M http statefull connection • easy to scale M • easy to reuse
  • 43. the fork long_running_job.sh be with you #!/bin/bash for count in `seq 1 100`; do echo $count sleep 0.1 done
  • 44. the fork long_running_server.js be with you var spawn = require("child_process").spawn, server = require("http").createServer() server.on("request", function(request, response) { var job = spawn("./long_running_job.sh") job.stdout.on("data", function(tick) { response.write(tick) }) job.on("exit", function() { response.end() }) })
  • 45. the fork be with you coder@apollo:~$ ab -c 1 -n 1 "http://localhost:8080/" ... Concurrency Level: 1 Time taken for tests: 10.531 seconds ... coder@apollo:~$ ab -c 1 -n 2 "http://localhost:8080/" ... Concurrency Level: 1 Time taken for tests: 20.108 seconds ...
  • 46. the fork be with you coder@apollo:~$ ab -c 2 -n 1 "http://localhost:8080/" ... Concurrency Level: 2 Time taken for tests: 10.634 seconds ... coder@apollo:~$ ab -c 100 -n 100 "http://localhost:8080/" ... Concurrency Level: 100 Time taken for tests: 11.198 seconds ... coder@apollo:~$ ab -c 500 -n 500 "http://localhost:8080/" ... Concurrency Level: 500 Time taken for tests: 31.082 seconds ...
  • 47. enter comet w at ch watch M spawn ch at w watch w w t a at ch ch
  • 49. INSTALL NPM (node packet manager) coder@apollo:~/Work/src/node/examples$ curl http://npmjs.org/install.sh | sh ... npm ok It worked coder@apollo:~/Work/src/node/examples$ npm search | wc -l 1918 coder@apollo:~/Work/src/node/examples$ npm install connect socket.io underscore coder@apollo:~/Work/src/node/examples$ npm list !"# connect@1.4.1 $ !"" mime@1.2.2 $ %"" qs@0.1.0 %"" socket.io@0.6.17 %"" underscore@1.1.6
  • 50. server/ routing progress_server.js var server = connect( connect.favicon(), connect.logger({"buffer": true}), connect.router(function(resource) { resource.post("/spawn", function(request, response) { ... }) }), connect.static(path.join(__dirname, "public"), {"cache": true}) )
  • 51. server/ routing progress_server.js resource.post("/spawn", function(request, response) { var job = spawn(path.join(__dirname, "bin", "job.sh")), id = ++counter response.writeHead(202, {"Content-Type": "plain/text"}) response.end("OKn") job.stdout.on("data", function(output) { var progress = parseInt(output.toString(), 10) _(connections).each(function(connection) { connection.send({"id": id, "progress": progress}) }) }) })
  • 52. server/ socket.io progress_server.js io.listen(server).on("connection", function(client) { connections[client.sessionId] = client client.on("disconnect", function() { delete connections[client.sessionId] }) })
  • 53. server/ simulation progress_server.js server.listen(port, host, function() { var spawnJobsInterval = setInterval(function() { http.request({ "port": port, "host": host, "method": "POST", "path": "/spawn" }).end() }, Math.floor(Math.random()*2000)+500) server.on("close", function() { clearInterval(spawnJobsInterval) process.exit() }) }) process.on("SIGINT", function() { server.close() })
  • 54. interface/html <html> <head> <title>Node.js - Long Running Jobs</title> <link href="css/style.css" rel="stylesheet" /> <script type="text/javascript" src="/socket.io/socket.io.js"></script> <script type="text/javascript" src="js/jquery-1.6.0.js"></script> <script type="text/javascript" src="js/progress.js"></script> index.html </head> <body> <div id="template"> <div class="progress-container"> <span class="progress-text">JOB/? - ?%</span> <div class="progress-bar"></div> </div> </div> <div id="container"> </div> </body> <script> ... </script> </html>
  • 55. interface/ socket.io <html> ... <script> $(function() { var socket = new io.Socket() index.html socket.on("connect", function() { }) socket.on("disconnect", function() { }) socket.on("message", function(job) { $("#template").progressBar(job.id, job.progress) }) socket.connect() }) </script> </html>
  • 56. interface/ progress bar $.fn.progressBar = function(id, progress) { var $template = $(this) $("#job-" + id) .otherwise(function() { return $template.children().clone() progress.js .attr("id", "job-" + id) .find(".progress-text").text("JOB/" + id + " - 0%").end() .appendTo("#container") }) .find(".progress-text").text("JOB/" + id + " - " + progress + "%").end() .find(".progress-bar").css("width", progress + "%").end() .tap(function() { if (progress === 100) { $(this) .find(".progress-bar").css("background-color", "red").end() .after(500, function() { $(this).fadeOut("slow", function() { $(this).remove() }) }) }
  • 57. interface/ progress bar $.fn.otherwise = function(ifNotFound) { if (this.length === 0) { return ifNotFound() } progress.js return this } $.fn.after = function(milliseconds, doSomething) { var self = this setTimeout(function() { doSomething.apply(self) }, milliseconds) return this } $.fn.tap = function() { var fn = Array.prototype.shift.apply(arguments) fn.apply(this, arguments) return this }
  • 58. we can do it with a little more “style”
  • 59. server/ event emitter var Job = (function() { var EventEmitter = require("events").EventEmitter, progress_server.js spawn = require("child_process").spawn, inherits = require("util").inherits function Job(id) { EventEmitter.call(this) this.id = id } inherits(Job, EventEmitter) Job.prototype.run = function() { return _(this).tap(function(job) { spawn(path.join(__dirname, "bin", "job.sh")) .stdout.on("data", function(output) { job.emit("progress", job.id, parseInt(output.toString(), 10)) }) }) } return Job })()
  • 60. server/ event emitter progress_server.js resource.post("/spawn", function(request, response) { new Job(++counter) .on("progress", function(id, progress) { _(connections).each(function(connection) { connection.send({"id": id, "progress": progress}) }) }) .run() response.writeHead(202, { "Content-Type": "plain/text" }) response.end("OKn") })
  • 61. node.js is awesome but when should i use it?
  • 62. when to use it? • chat/messaging • real-time applications • intelligent proxies • high concurrency applications • communication hubs • coordinators
  • 63. please tell me something bad about node.js
  • 64. some warnings • release stable 0.4.7 (young) • lots of stuffs to look at • lots of half backed stuffs • retro compatibility??? • bad at handling static contents • Bad at handling binary contents • hard to find organized and authoritative informations
  • 65. vs
  • 69. gabriele lana gabriele.lana@cleancode.it twitter: @gabrielelana http://joind.in/3359