workshop 4: nodejs. express framework & mongodb
TRANSCRIPT
Node.js, Express & MongoDBA brief introduction
Cristina Hernández &
Alberto Irurueta
What is Node.js?
- Is an implementation of a web server based on Javascript
- Is not a web framework, it’s a platform! (It’s like saying that .net is a web development framework)
Pros & Cons of Node.js
PROS:- Is very very efficient in
resources usage. - Javascript code is compiled.
- Runs on a single thread.- WTF?- Takes advantage of I/O locks to
handle several requests almost concurrently on a single thread.
- Useful for I/O, not for intensive computations
- On production systems typically one thread is spanned per processor
- Javascript both on frontend & backend
- Easier for designers
CONS:- Configuration on
Windows systems is a pain in the ass.
- Not useful for computation intensive tasks or enterprise applications.
http://blog.mixu.net/2011/02/01/understanding-
the-node-js-event-loop/
Runs on a single thread I
- All I/O call are non-blocking and event based
- Your code is the only part not running asynchronously, hence computation intensive code (i.e. computing an image thumbnail) blocks the whole server.
- Asynchronous code can be made using solutions similar to WebSockets, but then thread synchronization issues will appear.
It is typically better to run computationally intensive code in backend servers and use an API REST or similar.
Runs on a single thread II
- But how can we attend several requests on a single thread?
- A bit of history:- One process per request:
- process memory is copied for each request. Too much memory usage!
- One thread per request: - typically using POSIX accept(). Memory does not need to be copied but the OS has
additional work scheduling all the threads.
- Single asynchronous thread: - using select() multiple requests can be attended while waiting for other I/O operations
on other requests on the same thread! Less work for the OS!
POSIX accept: http://pubs.opengroup.org/onlinepubs/009695399/functions/accept.htm
POSIX select: http://linux.die.net/man/2/selectl
Node.js event based
var result = db.query("select x from table_Y");
doSomethingWith(result); //wait for result
doSomethingWithOutResult(); //execution is blocked!!
Sync:
Async:
db.query(“select x from table_Y”, function (result) {
doSomethingWith(result); //wait for result
});
doSomethingWithOutResult(); //executes without any delay!
callback!
Node.js comparison
- Asynchronous thread handling is not exclusive of node.js!- It is interesting for AJAX intensive applications or for
push model implementations (i.e. websockets, chats, etc)
- Other platforms have implemented this model too:- Java: Servlet API 3.0 (December 2009)
- ASP.NET: .NET platform 4.5 (August 2012)- PHP? Django?
Node.js installation
Mac OS X:- Go to: https://nodejs.org/en/- Click the big green button to download the setup
program.
Linux:sudo apt-get updatesudo apt-get install nodejssudo apt-get install npm
Running & debugging
- Starting/stopping: node <file.js>
- Debugging: nodemon --debug <file.js>
- Debugger: node-inspector
Installing nodemon && node-inspector:npm install nodemonnpm install node-inspector
Node.js - when to use it
- Chat / Messaging
- Real-Time applications
- High concurrency applications
http://stackoverflow.com/questions/5062614/how-to-decide-when-to-use-node-js
Node.js - Built-in modules
- assert- buffer- child_process- cluster- crypto- dgram- dns- events- fs- http- https- net
- os- path- punycode- querystring- readline- repl- string_decoder- tls- tty- url- util- vm- zlib
Node.js - FileSystem
var fs = require("fs");
// Asynchronous read
fs.readFile('input.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("Asynchronous read: " + data.toString());
});
// Synchronous read
var data = fs.readFileSync('input.txt');
console.log("Synchronous read: " + data.toString());
console.log("Program Ended");
What is Express?
It is a node.js based web framework
It’s the equivalent to a Servlet + web.xml in Java!
npm install --save express
Express - HTTP Server
var express = require('express');
var http = require('http');
//create express app
var app = express();
app.set('port', process.env.PORT || 3000);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
Express - Routing
app.get('/', function(request, response) {
response.send('¡Hello, Express!');
});
app.get('/users/:userName', function(request, response) {
var name = request.params.userName;
response.send('¡Hello, ' + name + '!');
});
//regex
app.get(/\/users\/(\d*)\/?(edit)?/, function (request, response) {
var message = 'user number #' + request.params[0];
if (request.params[1] === 'edit') {
message = Editing ' + message;
} else {
message = 'Viewing ' + message;
}
response.send(message);
});
handler
Express - Routing POST
app.post('/users', function(request, response) {
var username = request.body.username;
response.send('¡Hello, ' + username + '!');
});
Express doesn’t parse request body by default
app.use(express.bodyParser());
middleware
Express - View rendering
app.set('views', path.join(__dirname, '..', '..', 'templates'));
app.set('view engine', 'dust');
app.get('/', function(request, response) {
response.render('index', {
title: '¡Hello, Express!',
username: 'Benítez'
});
});
view parameters
Express - NODE_ENV
Linux and OSX: export NODE_ENV=production
Windows: SET NODE_ENV=production
- Environment variable NODE_ENV
- development
- production
- By default, Express switches on view caching on production
Express - Connect / Middlewares
function uselessMiddleware(req, res, next) { next() }
// A middleware that simply interrupts every request
function worseThanUselessMiddleware(req, res, next) {
next("Hey are you busy?")
}
- Connect is an extensible HTTP server framework for node, providing high performance "plugins" known as middleware.
- A middleware is simply a function with three arguments: request, response, next
error -> request interruption
Express - Connect / Middlewares
// a middleware mounted on /user/:id; will be executed for any type of HTTP
request to /user/:id
app.use('/user/:id', function (req, res, next) {
console.log('Request Type:', req.method);
next();
})
// a middleware with no mount path; gets executed for every request to the app
app.use(function (req, res, next) {
console.log('Time:', Date.now());
next();
});
Express - Router-level middleware
var app = express();
var router = express.Router();
// shows request info for any type of HTTP request to /user/:id
router.use('/user/:id', function(req, res, next) {
console.log('Request URL:', req.originalUrl);
next();
}, function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
// mount the router on the app
app.use('/', router);
Express - Error Handling
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
- Error-handling middleware always takes fourarguments.
Express - Official middlewares
MongoDB
It’s a non relational databaseIt’s non-transactional: Only guarantees that read/write operations are atomic, but rollback cannot be doneBetter performance than most relational databasesNot suitable for highly concurrent applications (i.e. commerce or financial applications where account balances or product stock must be synchronized between requests).Suitable to work on non-concurrent and large amounts of data (i.e. timeline, logging, analytics, etc)Uses Javascript as programming language!MongooseOther relational & non-relational databases
MongoDB - NoSQL Database
NoSQL Database - Not Only SQL Database
Many different types: - key-value stores
- document databases
- wide-column stores
- graph databases
MongoDB - SQL vs NoSQL
SQL Databases
- Individual records stored as rows in tables
- Structure and data types fixed in advance
- Transactional- Consistent
NoSQL Databases
- Document: table-and-row model stored in single document
- Dynamic structure- Atomic operations- Not all, MongoDB is
consistent
MongoDB - setup
It’s a node package:
Start database (from cmd):
npm install mongodb
https://www.mongodb.org/
mongod //service
mongo
default port is 27017
MongoDB - structure
Database
Collection Collection Collection
Document Document
SQL
Database
Database
Table
Row
MongoDB
var Mongo = require(“mongodb”).MongoClient;
//connect to ‘test’, if not exists, create itMongo.connect(“mongodb://localhost:27017/test”, function(err, db){
if(!err){ //We are connectedvar collection = db.collection(‘users’);//insert into collection, if not exists, create itcollection.insert({name:’Lionel’, apellidos:’Messi’}, function(err,
collection){});collection.update({apellidos:’Messi’}, {$set:{name:’D10S’}});collection.remove({apellidos:’Messi’});
}});
MongoDB
var stream = db.find({apellidos:’Messi’}).stream();
stream.on(“data”, function(item){//fired on each result found
});
stream.on(“end”, function() {//fired when there is no more document to look for
});