Upload
akshay-mathur
View
2.527
Download
2
Tags:
Embed Size (px)
DESCRIPTION
Introduction to NodeJS
Citation preview
AKSHAY MATHUR
@AKSHAYMATHU
Getting Started with
@akshaymathu
2
Ground Rules
Post on FB and Tweet nowDisturb Everyone during
the session Not by phone rings Not by local talks By more information and
questions
@akshaymathu
3
Let’s Know Each Other
Do you code?OS?Node?JavaScript, JSON?Web Development?CoffeeScriptOther Programing Language?Why are you attending?
@akshaymathu
4
Akshay Mathur
Founding Team Member of ShopSocially (Enabling “social” for retailers) AirTight Neworks (Global leader of WIPS)
15+ years in IT industry Currently Principal Architect at ShopSocially Mostly worked with Startups
From Conceptualization to Stabilization At different functions i.e. development, testing, release With multiple technologies
@akshaymathu
5
JavaScript
Born in 1995 at NetscapeNot at all related to JavaSyntax influenced by CInterpreted ECMA scripting languageDynamically typedObject Oriented as well as FunctionalPrototype based
@akshaymathu
6
Typical Usage
Web programing Client side
Web pages Browser plugins
Server side SSJS (not in use) NodeJS
PDF documentsDesktop WidgetsMongoDB
@akshaymathu
7
NodeJS
JavaScript Runtime at command line Allows us to write JS programs outside browser
Built on V8 JS engine V8 is open source JS engine developed by Google It also powers Google Chrome Written in C++ Compiles JS code to native before execution
@akshaymathu
8
Good for
For IO heavy apps Web socket (chat) server Real time collaborative editor Fast file uploads Ad server Any other real time data app (e.g. streaming server) Crawler Asynchronous chaining of tasks
NOT good for CPU heavy apps Weather prediction
May not be good for big projects
@akshaymathu
9
NodeJS is NOT
A web framework Provides tools to create a web server
Multi threaded Is Single threaded, event driven, asynchronous, non-
blocking
For beginners Needs programing at very low level You start with writing a web server
@akshaymathu
10
Possible Issues
Can not utilize multicore processer because of single thread Managing multiple processes from outside may be even bigger
problemAny CPU intensive task delays all the requestsRequires constant attention (non-traditional thinking)
for not having blocking codeIn case of big products the code/logic gets distributed
in multiple callback functionsIf data needs to collected from different places and
correlated, synchronizing all callbacks becomes toughGarbage collection may also be an issue
SINGLE THREADED EVENT DRIVEN
ASYNCHRONOUSNON-BLOCKING
What Jargons Mean
@akshaymathu
12
Single Threaded
New Node process does not start for every request
Only one code executes at a time Everything else remains in the queue No worry about different portions of code accessing the
same data structures at the same timeDelay at one place delays everything after that Can not take advantage of multi-core CPU
Then how NodeJS is fast?
@akshaymathu
13
Non-blocking
There is only one process that is executing If the process waits for something to complete,
everything else gets delayed
So the code has to be structured in a way that wait for IO happens outside the main execution
@akshaymathu
14
Blocking Vs. Non-blocking
var a = db.query('SELECT * from huge_table’);console.log('result a:’, a);
console.log(‘Doing something else’);
Blocking I/O
Non-Blocking I/Odb.query('SELECT * from huge_table’, function(res) { console.log('result a:’, res);});
console.log(‘Doing something else’);
@akshaymathu
15
Asynchronous
Not all code is executed in the same order it is written
Node (and you) divide the code into small pieces and fire them in parallel
Typically the code announces its state of execution (or completion) via events
@akshaymathu
16
Event Driven
A code block gets into the queue of execution when an event happens It gets executed on its turn
Anyone can raise (or listen to) an event System Some library (module) Your code
You have the choice (and ways) to attach a code block to an event Also known as event callbacks
@akshaymathu
17
The Event Queue
@akshaymathu
18
‘King and Servants’ Analogy… by Felix Geisendörfer
everything runs in parallel, except your code. To understand that, imagine your code is the king, and node is his army of servants.
The day starts by one servant waking up the king and asking him if he needs anything. The king gives the servant a list of tasks and goes back to sleep a little longer. The servant now distributes those tasks among his colleagues and they get to work.
Once a servant finishes a task, he lines up outside the kings quarter to report. The king lets one servant in at a time, and listens to things he reports. Sometimes the king will give the servant more tasks on the way out.
Life is good, for the king's servants carry out all of his tasks in parallel, but only report with one result at a time, so the king can focus.
@akshaymathu
DO THEY OCCUR ON SERVER AS WELL?
Events
@akshaymathu
21
Events we know…
The event familiar to us are Click Focus Blur Hover
These events are raised when user interacts with DOM elements
But the DOM is not being rendered in NodeJS
Then what events are we talking about in NodeJS?
@akshaymathu
22
Node Events
The most common event that a web server uses is request Raised when a web request (url) hits the server
Other events: When chunk of multipart data (file) is received When all chunks of file are received When system finishes reading a file When data set is returned by a database query …
You can define your own events using event emitter
@akshaymathu
23
Let’s Revise: JS Function Facts
Function is a block of a code that gets executed when called
JS function may not have a name Anonymous functions can be used
JS function accept any data type as argumentFunction is a valid data type in JSA function can be assigned to a variableA function can be passed as an argument to
another functionA function can be defined inside another
function
@akshaymathu
24
Event Callback
Because the system is single threaded And we do not want to block it for I/O We use asynchronous functions for getting work done
We depend on the events to tell when some work is finished And we want some code to execute when the event
occursAsynchronous functions take a function as an
additional argument and call the function when the event occurs This function is known as callback function
@akshaymathu
25
Callback in Action
callback = function(res) { console.log('result a:’, res);};db.query('SELECT * from huge_table’, callback);
Or
db.query('SELECT * from huge_table’, function(res) { console.log('result a:’, res);});
@akshaymathu 26
NOTHING BUT LIBRARIES
Node Modules
@akshaymathu
28
Available Modules
Modules are nothing but collections of useful functions Otherwise we call them libraries
Built-in modules come with NodeJS installation http, tcp, url, dns, buffer, udp etc.
People create more modules, package and publish them for others to use less, coffee, express etc. 1000+ modules are available via npm
You can write your own custom module for organizing your code better
@akshaymathu
29
Creating Custom Module
Write some useful code in a file Some function(s) achieving a goal
Decide what should be available outside for others to use Public API of your module
Make the APIs available outside using exports object
my_api = function(){…};exports.myApi = my_api;
@akshaymathu
30
Using Modules
‘require’ functions loads a moduleWhatever has been exported becomes
available with ‘require’ and can be assigned to a variable for later use
var http = require(‘http’);
var custom = require(‘./my_api’);custom.myApi();
@akshaymathu 31
@akshaymathu
32
A SIMPLE WEB SERVER
Let’s Program
@akshaymathu
33
Hello World
Just one line is needed to write to STDOUTconsole.log(‘Hello World’)
Running the file with Node just worksnode hello_world.js
@akshaymathu
34
Minimalistic HTTP Server
var http = require("http");
on_request = function(request, response) { response.writeHead(200,
{"Content-Type": "text/plain"});
response.write("Hello World");
response.end(); };http.createServer(on_request).listen(8888);Console.log(‘Server Started’);
@akshaymathu
35
Improving the Server
Running this server with Node starts the servernode server.js
The server always returns same string Try any url, browser always says “Hello World”
Actually the server should respond content based on URL It should route the request to proper handler Handler should return proper content
@akshaymathu
36
Organizing Code
Rather than writing everything in single file, it is a good idea to divide the code into logical modules Main startup file: index.js Web server: server.js URL Router: routes.js Request Handler: requestHandlers.js …
More files and directories will come as the code grows
@akshaymathu
37
Initial Server Module
var http = require("http"); function start() {
function onRequest(request, response){console.log("Request received."); response.writeHead(200,
{"Content-Type": "text/plain"}); response.write("Hello World"); response.end();
} http.createServer(onRequest).listen(8888); console.log("Server has started.");
}exports.start = start;
@akshaymathu
38
Initial Startup File
As server became a module and exposes a start function, we need to load server module Call start function to start the server
var server = require("./server"); server.start();
Running the main file with now starts the servernode index.js
But it still returns ‘Hello world’ for all URLs
@akshaymathu
39
Let’s Revise: Parts of URL
https://sub.domain.com:8086/a/folder/file.html?key=val&key=val2#some_place
ProtocolSub-domain, Domain and TLDPortPathFileQuery stringFragment
@akshaymathu
40
Server – Router Interaction
For routing the requests based on URL, the router must know pathname of the requested URL The URL can be read from the ‘request’ object available in
server moduleSo what should we pass to the router?
Request object URL (Extract URL from request in server) Pathname (Extract and parse URL in server) ??
If server need to call router, how router becomes available to server?
@akshaymathu
41
Initial Router
function route(pathname) {console.log("About to route a
request for " + pathname);
}
exports.route = route;
@akshaymathu
42
Router Aware Server
var http = require("http"); var url = require("url"); function start(route) {
function onRequest(request, response){
var pathname = url.parse(request.url).pathname;
route(pathname); response.writeHead(200, "Content-Type": "text/plain"});
response.write("Hello World"); response.end();
} http.createServer(onRequest).listen(8888);
}exports.start = start;
@akshaymathu
43
Making Router Available to Server
Router is made available as an argument (dependency) to server’s ‘start’ function This is also known as dependency injection
var server = require("./server"); var router = require("./router");
server.start(router.route);
Router module is loaded in startup file and the route function is passed at the time of starting server
Server then calls route function of the router with the pathname
@akshaymathu
44
Adding Request Handlers
The actual work of creating response for a request will be done by Request Handlers We need to add these handlers to the server
The requestHandlers module will consist of a function corresponding to each expected URL
At some place, we also need mapping between URL and the request handler function
@akshaymathu
45
Initial Request Handlers
function start() {console.log("Request for 'start’.");return "Hello Start";
} function upload() {
console.log("Request for 'upload.");return "Hello Upload";
}
exports.start = start; exports.upload = upload;
@akshaymathu
46
Including Handlers
var server = require("./server");var router = require("./router");var requestHandlers =
require("./requestHandlers");
var handle = {}handle["/"] = requestHandlers.start; handle["/start"] = requestHandlers.start; handle["/upload"] = requestHandlers.upload;
server.start(router.route, handle);
@akshaymathu
47
Change in Server
function start(route, handle) {function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
content = route(handle, pathname); response.writeHead(200, {"Content-Type":
"text/plain"});
response.write(content); response.end();
} http.createServer(onRequest).listen(8888);
console.log("Server has started."); } exports.start = start;
@akshaymathu
48
Real Routing
function route(handle, pathname) {
console.log(”Routing request for " + pathname);
if (typeof handle[pathname] === 'function') {
return handle[pathname]();
} else { console.log("No request handler found for " + pathname); }
}
exports.route = route;
@akshaymathu 49
@akshaymathu
50
Done
Did we do everything Correct?
Nop
@akshaymathu
51
What is wrong?
function start(route, handle) {function onRequest(request, response) {
var pathname =
url.parse(request.url).pathname;
content = route(handle, pathname);
response.writeHead(200, {"Content-Type": "text/plain"});
response.write(content); response.end(); } http.createServer(onRequest).listen(8888); console.log("Server has
started.");
} exports.start = start;
Blocking Code
@akshaymathu
52
What are the problems?
The way ‘content’ is being collected and being written to response, it forces to write blocking synchronous code in handlers Because handler has to return content when called
If you write asynchronous code in handler, the server will always return response with no content Because handler will return nothing and when
callback will return with the content, there will be no one to collect the output
@akshaymathu
53
The Right Way
The content should be written into response object when the content becomes available
So the response object should be made available to request handlers Response object is available in server
Server is not directly calling request handlers So first, Response object will be passed to router And then, Router will pass it to request handlers
@akshaymathu
54
Corrected Server
var http = require("http"); var url = require("url");
function start(route, handle) {function onRequest(request, response) { var pathname = url.parse(request.url).pathname; console.log("Request for " + pathname);
route(handle, pathname, response); }
http.createServer(onRequest).listen(8888); console.log("Server has started."); }
exports.start = start;
@akshaymathu
55
Corrected Router
function route(handle, pathname, response) { console.log(”Routing request for " + pathname); if (typeof handle[pathname] === 'function') {
handle[pathname](response);
} else { console.log("No handler found for " + pathname); response.writeHead(404, {"Content-Type": "text/plain"}); response.write("404 Not found"); response.end(); }
} exports.route = route;
@akshaymathu
56
Corrected Handlers
function start(response) {db.query(”select * from huge_table”,
function (error, stdout, stderr) { response.writeHead(200, {"Content-Type": "text/plain"}); response.write(stdout);response.end();
}); } exports.start = start;
@akshaymathu
57
Done
Did we do everything Correct?
Yep
@akshaymathu 58
@akshaymathu
59
Summary
Node will require extra work and different thought process But it will pay off for it
Choose Node carefully only for the type of app it is best suited
You may not need to write code at the lowest level we discussed here You may want to choose framework
@akshaymathu
60
MVC in Node
Express (Controller)
Mongoose (Model)
Jade (View)
More …
@akshaymathu
61
Thanks
@akshaymathu