SlideShare a Scribd company logo
1 of 31
Download to read offline
Koajs as an alternative to Express
I am Mykola Kozhuharenko
front-end dev in Krusche & Company
I’m on github
Hello!
Nodejs/Express downsides:
◉Code readability
Callback hell
◉Error handling
Duplicate callbacks / cb call might be lost in third
party library
If you miss an error handler - you are in troubles
Can't throw an error or use try/catch
app.post('/',function (req, res, next) {
var body = req.body;
if (!body.name || !body.email || !body.password) {
return res.status(400).send("Missing username or email or password")
};
// case #1- if user was registered (socials platform) before -> just add a password;
User.findOneAndUpdate({
email: body.email
}, {
$set: {password: body.password}
}, (err, user) => {
if (!user) {
// case #2 - user has never been registering before -> create new one;
User.create(body, (err, user) => {
if (err && err.name === 'ValidationError') {
return res.status(400).send(err)
} else if (err) {
return res.status(500).send(err)
}
return res.send({ user: user })
});
} else {
return res.send({ user: body })
}
});
});
Callbacks
User.findOneAndUpdate({
email: body.email
}, {
$set: {password: body.password}
}, (err, user) => {
if (err) {
return res.status(500).send(err)
}
if (!user) {
// case #2 - user has never been registering before -> create new one;
User.create(body, (err, user) => {
if (err && err.name === 'ValidationError') {
return res.status(400).send(err)
} else if (err) {
return res.status(500).send(err)
}
return res.send({ user: user })
});
} else {
return res.send({ user: body })
}
});
Callbacks
◉ If you miss an error handler -
you are in troubles
◉ Duplicate callbacks / cb call
might be lost in third party
library
// foo is a function that returns a generator
function *foo() {
console.log('start');
yield 1;
console.log('second');
yield 2;
yield 3;
}
var gen = foo(); // get a generator object
gen.next() // 'start', { value: 1, done:false }
gen.next() // 'second', { value: 2, done:false }
gen.next() // { value: 3, done:false }
gen.next() // { value: undefined, done:true }
Generators #1
const Message = require('./models/message');
function *foo() {
yield new Promise((resolve, reject) => {
resolve("Hello")
});
yield Message.create({text: 'some text');
}
var gen = foo();
var genVal = gen.next().value // { value: Promise, done:false }
genVal.then(res => console.log(res)) // Hello
gen.next() // { value: Promise, done:false }
Generators #2 - Promises
const Message = require('./models/message');
function *foo() {
var greeting = yield new Promise.resolve('Hello');
var result = yield Message.create({text: greeting});
console.log(result) // saved! {id: 'ID', text: 'Hello'}
}
var gen = foo();
gen.next().value // Promise
.then(greeting => {
console.log(greeting); // 'Hello'
gen.next(greeting).value // Promise
.then(createRes = gen.next(createRes))
})
Generators #3 - Two ways
var fetch = require('isomorphic-fetch');
function *foo() {
try {
var greeting = yield fetch('/api/get-greetings')[0];
} catch (e) {
console.log(e);
}
}
var gen = foo();
gen.next().value
.then(greeting => gen.next(greeting))
.catch(e => gen.throw(e))
Generators #4 - throw
function runner (gen) {
var gen = gen();
next(null, null);
function next(err, res) {
const res = err ? gen.throw(err) : gen.next(res);
if (res.done) return;
res.value
.then((res) => next(null, res))
.catch((error) => next(error));
}
};
runner(function *foo() {
var greeting = yield Promise.resolve("Hello")
var name = yield Promise.resolve("John")
console.log(greeting, name); // 'Hello John'
})
Generators #5 - Runner
var co = require('co')
app.post('/',function (req, res, next) {
var body = req.body;
co(function *() {
try {
var user = yield User.findOneAndUpdate({
email: body.email
}, { $set: {password: body.password} });
if (!user) {
user = yield User.create(body);
}
res.send({ user: user })
} catch (e) {
if (err && err.name === 'ValidationError') {
return res.status(400).send(err)
} else if (err) {
return res.status(500).send(err)
}
}
});
});
Co
Using Co you can yield:
Thunks
(will be deprecated)
Arrays
co(function* () {
// parallel
var res = yield [
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3),
];
console.log(res); // => [1, 2, 3]
}).catch(onerror);
Generators
function* greet() {
return yield new Promise((resolve, rej) => {
resolve("Hello, Mary!")
});
}
co(function *(){
var greeting = yield greet
console.log(greeting)
}).catch((err) => {
console.log(err)
});
Promises
Co
Along with co will be useful:
◉mz - promisify NodeJS core modules
◉Thenify promisify any callback-based function
var fs = require('mz/fs')
fs.exists(__filename).then(function (exists) {
if (exists) // do something
})
var thenify = require('thenify');
var somethingAsync = thenify(function somethingAsync(a, b, c, callback) {
callback(null, a, b, c);
});
Adopted by community
Callbacks Async Promises Generators
(along with co)
Meet Koa!
Philosophically, Koa aims to "fix and replace node",
whereas Express "augments node"
Koa Hello world
var koa = require('koa');
var app = koa();
app.use(function *() {
this.body = 'Hello World';
});
app.listen(3000);
Koa API
koa Request
CONTEXT
this.request
this.response
koa Response
this.query
this.url
this.headers
this.get - get a header
this.body
this.type - get content-type
this.redirect
this.status
this.set -set a header
app.use(function *(next) {
var start = new Date; // <<<------ 1
yield next; // waits for downstream middlewares
var delta = Math.ceil(Date.now() - start); // <<<------ 3
console.info(`${this.method} ${this.url} - ${delta}ms`);
this.set('X-Response-Time', delta + 'ms'); // <<<------ 4
});
app.use(function *() {
this.body = yield new Promise.resolve([10000]); // <<<------ 2
});
Response time - Koa middleware
3
4
2
1
Custom error
app.use(function *(next) {
try {
yield next;
} catch (e) {
if (e instanceof AuthError) {
this.statusCode = e.status;
this.redirect('/not-authorized');
this.body = this.render('not-authorized');
} else if (e.status) {
this.statusCode = e.status;
this.body = this.render('error', e);
} else {
this.statusCode = 500;
this.body = this.render('error', e);
logger.error('Unexpected error: ', e); // winston
}
}
});
app.use(function *(next) {
throw new AuthError()
});
app.post('/',function (req, res, next) {
var body = req.body;
if (!body.name || !body.email || !body.password) {
return res.status(400).send("Missing username or email or password")
};
// case #1- if user was registered (socials platform) before -> just add a password;
User.findOneAndUpdate({
email: body.email
}, { $set: {password: body.password} }, (err, user) => {
if (err) return res.status(500).send(err)
if (!user) {
// case #2 - user has never been registering before -> create new one;
User.create(body, (err, user) => {
if (err && err.name === 'ValidationError') {
return res.status(400).send(err)
} else if (err) {
return res.status(500).send(err)
}
return res.send({ user: user })
});
} else {
return res.send({ user: body })
}
});
});
Do you remember this example with callbacks?
app.use(function *(next) {
try {
yield next;
} catch (e) {
if (e.status) { // app error
this.body = e.message;
this.statusCode = e.status;
} if else (e && e.name ===
'ValidationError') {
this.body = e;
this.statusCode = 400;
} else { // Internal server error
this.body = "Oops!";
this.status = 500;
}
}
});
Koa way
app.use(function *(next) {
var body = this.request.body;
if (!body.name || !body.email || !body.password) {
throw new Error("Missing username||email||password");
}
var user = yield User.findOneAndUpdate({email: body.email}, {
$set: {password: body.password}
});
if (!user) user = yield User.create(body);
this.body = { user: this.body };
});
2nd middleware
1st middleware
app.get('/', function (req, res, next) {
var readStream = fs.createReadStream('text.txt');
readStream.pipe(res);
readStream.on('error', () => {
res.statusCode = 500;
res.end('Server error has occurred!');
});
res.on('close', () => readStream.destroy());
});
Send a file
app.use(function* (next) {
this.body = fs.createReadStream('text.txt')
});
Express/node
Koa
“
“Koa and express uses the same modules.
We’ve refactored express into jshttp and
pillarjs so that anyone else can make their
own framework as well”
Express & Koa similarities
Same modules
Accepts, content-type,
cookie, fresh, content-
disposition, on-finished,
parseurl, type-is, vary,
escape-html
Modular
Each feature is moved to a
separate module.
Minimalistic
Contains only essential
(core) modules (e.g.
headers parsing).
Same developers
Koa was build by core
developers of Express:
TJ Holowaychuk and
others
Koa middlewares:
◉koa-router
◉koa-bodyparse
◉koa-static
◉koa-session
◉koa-compress
◉koa-cors
◉Koa-logger
more here
Koa
◉ router
◉ bigger community
◉ needs domains to catch async
errors
◉ close to node style
◉ a lot of outdated examples and
tutorials
Express
vs
◉ better error handling with try catch
◉ nice async flow control (no cb hell)
◉ api is more stable;
◉ no build-in router
◉ smaller community
◉ support stream out of the box
◉ easy to understand source code; no
monkey patching
Any questions ?
Thanks!

More Related Content

What's hot

Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)andrewnacin
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationKirill Chebunin
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkJeremy Kendall
 
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)James Titcumb
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupKacper Gunia
 
Symfony2 Service Container: Inject me, my friend
Symfony2 Service Container: Inject me, my friendSymfony2 Service Container: Inject me, my friend
Symfony2 Service Container: Inject me, my friendKirill Chebunin
 
PhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examplesPhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examplesMarcello Duarte
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICKonstantin Kudryashov
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsIgnacio Martín
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersKacper Gunia
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony TechniquesKris Wallsmith
 
jQuery: out with the old, in with the new
jQuery: out with the old, in with the newjQuery: out with the old, in with the new
jQuery: out with the old, in with the newRemy Sharp
 
jQuery Plugin Creation
jQuery Plugin CreationjQuery Plugin Creation
jQuery Plugin Creationbenalman
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mockingKonstantin Kudryashov
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your AppLuca Mearelli
 
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...Arc & Codementor
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf Conference
 

What's hot (20)

Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 Application
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
 
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
 
Symfony2 Service Container: Inject me, my friend
Symfony2 Service Container: Inject me, my friendSymfony2 Service Container: Inject me, my friend
Symfony2 Service Container: Inject me, my friend
 
Coffee Script
Coffee ScriptCoffee Script
Coffee Script
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
PhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examplesPhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examples
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
Puppet modules for Fun and Profit
Puppet modules for Fun and ProfitPuppet modules for Fun and Profit
Puppet modules for Fun and Profit
 
jQuery: out with the old, in with the new
jQuery: out with the old, in with the newjQuery: out with the old, in with the new
jQuery: out with the old, in with the new
 
jQuery Plugin Creation
jQuery Plugin CreationjQuery Plugin Creation
jQuery Plugin Creation
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
 
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 

Similar to Koajs as an alternative to Express - OdessaJs'16

node.js practical guide to serverside javascript
node.js practical guide to serverside javascriptnode.js practical guide to serverside javascript
node.js practical guide to serverside javascriptEldar Djafarov
 
2013-06-15 - Software Craftsmanship mit JavaScript
2013-06-15 - Software Craftsmanship mit JavaScript2013-06-15 - Software Craftsmanship mit JavaScript
2013-06-15 - Software Craftsmanship mit JavaScriptJohannes Hoppe
 
2013-06-24 - Software Craftsmanship with JavaScript
2013-06-24 - Software Craftsmanship with JavaScript2013-06-24 - Software Craftsmanship with JavaScript
2013-06-24 - Software Craftsmanship with JavaScriptJohannes Hoppe
 
Ember.js for a CakePHP Developer
Ember.js for a CakePHP DeveloperEmber.js for a CakePHP Developer
Ember.js for a CakePHP Developerjtrapp07
 
JSLab. Домников Виталий. "ES6 генераторы и Koa.js"
JSLab. Домников Виталий. "ES6 генераторы и Koa.js"JSLab. Домников Виталий. "ES6 генераторы и Koa.js"
JSLab. Домников Виталий. "ES6 генераторы и Koa.js"GeeksLab Odessa
 
Going crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHPGoing crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHPMariano Iglesias
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is hereSebastiano Armeli
 
Build web application by express
Build web application by expressBuild web application by express
Build web application by expressShawn Meng
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developersStoyan Stefanov
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Seri Moth
 
Javascript: the important bits
Javascript: the important bitsJavascript: the important bits
Javascript: the important bitsChris Saylor
 
Introduction to PHP
Introduction to PHPIntroduction to PHP
Introduction to PHPBradley Holt
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in SwiftPeter Friese
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5arajivmordani
 
All you need to know about JavaScript Functions
All you need to know about JavaScript FunctionsAll you need to know about JavaScript Functions
All you need to know about JavaScript FunctionsOluwaleke Fakorede
 
Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015Lukas Ruebbelke
 

Similar to Koajs as an alternative to Express - OdessaJs'16 (20)

node.js practical guide to serverside javascript
node.js practical guide to serverside javascriptnode.js practical guide to serverside javascript
node.js practical guide to serverside javascript
 
Node.js - Best practices
Node.js  - Best practicesNode.js  - Best practices
Node.js - Best practices
 
2013-06-15 - Software Craftsmanship mit JavaScript
2013-06-15 - Software Craftsmanship mit JavaScript2013-06-15 - Software Craftsmanship mit JavaScript
2013-06-15 - Software Craftsmanship mit JavaScript
 
2013-06-24 - Software Craftsmanship with JavaScript
2013-06-24 - Software Craftsmanship with JavaScript2013-06-24 - Software Craftsmanship with JavaScript
2013-06-24 - Software Craftsmanship with JavaScript
 
Ember.js for a CakePHP Developer
Ember.js for a CakePHP DeveloperEmber.js for a CakePHP Developer
Ember.js for a CakePHP Developer
 
JSLab. Домников Виталий. "ES6 генераторы и Koa.js"
JSLab. Домников Виталий. "ES6 генераторы и Koa.js"JSLab. Домников Виталий. "ES6 генераторы и Koa.js"
JSLab. Домников Виталий. "ES6 генераторы и Koa.js"
 
Going crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHPGoing crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHP
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is here
 
Build web application by express
Build web application by expressBuild web application by express
Build web application by express
 
ES6: Features + Rails
ES6: Features + RailsES6: Features + Rails
ES6: Features + Rails
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 
Javascript: the important bits
Javascript: the important bitsJavascript: the important bits
Javascript: the important bits
 
Introduction to PHP
Introduction to PHPIntroduction to PHP
Introduction to PHP
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in Swift
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
 
All you need to know about JavaScript Functions
All you need to know about JavaScript FunctionsAll you need to know about JavaScript Functions
All you need to know about JavaScript Functions
 
Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015
 
Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
 

Recently uploaded

Cybersecurity Threats and Cybersecurity Best Practices
Cybersecurity Threats and Cybersecurity Best PracticesCybersecurity Threats and Cybersecurity Best Practices
Cybersecurity Threats and Cybersecurity Best PracticesLumiverse Solutions Pvt Ltd
 
IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119APNIC
 
Company Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptxCompany Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptxMario
 
TRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptxTRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptxAndrieCagasanAkio
 
Summary ID-IGF 2016 National Dialogue - English (tata kelola internet / int...
Summary  ID-IGF 2016 National Dialogue  - English (tata kelola internet / int...Summary  ID-IGF 2016 National Dialogue  - English (tata kelola internet / int...
Summary ID-IGF 2016 National Dialogue - English (tata kelola internet / int...ICT Watch - Indonesia
 
办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...
办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...
办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...vmzoxnx5
 
How to login to Router net ORBI LOGIN...
How to login to Router net ORBI LOGIN...How to login to Router net ORBI LOGIN...
How to login to Router net ORBI LOGIN...rrouter90
 
Summary IGF 2013 Bali - English (tata kelola internet / internet governance)
Summary  IGF 2013 Bali - English (tata kelola internet / internet governance)Summary  IGF 2013 Bali - English (tata kelola internet / internet governance)
Summary IGF 2013 Bali - English (tata kelola internet / internet governance)ICT Watch - Indonesia
 
Unidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptxUnidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptxmibuzondetrabajo
 

Recently uploaded (9)

Cybersecurity Threats and Cybersecurity Best Practices
Cybersecurity Threats and Cybersecurity Best PracticesCybersecurity Threats and Cybersecurity Best Practices
Cybersecurity Threats and Cybersecurity Best Practices
 
IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119
 
Company Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptxCompany Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptx
 
TRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptxTRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptx
 
Summary ID-IGF 2016 National Dialogue - English (tata kelola internet / int...
Summary  ID-IGF 2016 National Dialogue  - English (tata kelola internet / int...Summary  ID-IGF 2016 National Dialogue  - English (tata kelola internet / int...
Summary ID-IGF 2016 National Dialogue - English (tata kelola internet / int...
 
办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...
办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...
办理澳洲USYD文凭证书学历认证【Q微/1954292140】办理悉尼大学毕业证书真实成绩单GPA修改/办理澳洲大学文凭证书Offer录取通知书/在读证明...
 
How to login to Router net ORBI LOGIN...
How to login to Router net ORBI LOGIN...How to login to Router net ORBI LOGIN...
How to login to Router net ORBI LOGIN...
 
Summary IGF 2013 Bali - English (tata kelola internet / internet governance)
Summary  IGF 2013 Bali - English (tata kelola internet / internet governance)Summary  IGF 2013 Bali - English (tata kelola internet / internet governance)
Summary IGF 2013 Bali - English (tata kelola internet / internet governance)
 
Unidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptxUnidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptx
 

Koajs as an alternative to Express - OdessaJs'16

  • 1. Koajs as an alternative to Express
  • 2. I am Mykola Kozhuharenko front-end dev in Krusche & Company I’m on github Hello!
  • 3. Nodejs/Express downsides: ◉Code readability Callback hell ◉Error handling Duplicate callbacks / cb call might be lost in third party library If you miss an error handler - you are in troubles Can't throw an error or use try/catch
  • 4. app.post('/',function (req, res, next) { var body = req.body; if (!body.name || !body.email || !body.password) { return res.status(400).send("Missing username or email or password") }; // case #1- if user was registered (socials platform) before -> just add a password; User.findOneAndUpdate({ email: body.email }, { $set: {password: body.password} }, (err, user) => { if (!user) { // case #2 - user has never been registering before -> create new one; User.create(body, (err, user) => { if (err && err.name === 'ValidationError') { return res.status(400).send(err) } else if (err) { return res.status(500).send(err) } return res.send({ user: user }) }); } else { return res.send({ user: body }) } }); }); Callbacks
  • 5. User.findOneAndUpdate({ email: body.email }, { $set: {password: body.password} }, (err, user) => { if (err) { return res.status(500).send(err) } if (!user) { // case #2 - user has never been registering before -> create new one; User.create(body, (err, user) => { if (err && err.name === 'ValidationError') { return res.status(400).send(err) } else if (err) { return res.status(500).send(err) } return res.send({ user: user }) }); } else { return res.send({ user: body }) } }); Callbacks
  • 6. ◉ If you miss an error handler - you are in troubles ◉ Duplicate callbacks / cb call might be lost in third party library
  • 7. // foo is a function that returns a generator function *foo() { console.log('start'); yield 1; console.log('second'); yield 2; yield 3; } var gen = foo(); // get a generator object gen.next() // 'start', { value: 1, done:false } gen.next() // 'second', { value: 2, done:false } gen.next() // { value: 3, done:false } gen.next() // { value: undefined, done:true } Generators #1
  • 8. const Message = require('./models/message'); function *foo() { yield new Promise((resolve, reject) => { resolve("Hello") }); yield Message.create({text: 'some text'); } var gen = foo(); var genVal = gen.next().value // { value: Promise, done:false } genVal.then(res => console.log(res)) // Hello gen.next() // { value: Promise, done:false } Generators #2 - Promises
  • 9. const Message = require('./models/message'); function *foo() { var greeting = yield new Promise.resolve('Hello'); var result = yield Message.create({text: greeting}); console.log(result) // saved! {id: 'ID', text: 'Hello'} } var gen = foo(); gen.next().value // Promise .then(greeting => { console.log(greeting); // 'Hello' gen.next(greeting).value // Promise .then(createRes = gen.next(createRes)) }) Generators #3 - Two ways
  • 10. var fetch = require('isomorphic-fetch'); function *foo() { try { var greeting = yield fetch('/api/get-greetings')[0]; } catch (e) { console.log(e); } } var gen = foo(); gen.next().value .then(greeting => gen.next(greeting)) .catch(e => gen.throw(e)) Generators #4 - throw
  • 11. function runner (gen) { var gen = gen(); next(null, null); function next(err, res) { const res = err ? gen.throw(err) : gen.next(res); if (res.done) return; res.value .then((res) => next(null, res)) .catch((error) => next(error)); } }; runner(function *foo() { var greeting = yield Promise.resolve("Hello") var name = yield Promise.resolve("John") console.log(greeting, name); // 'Hello John' }) Generators #5 - Runner
  • 12. var co = require('co') app.post('/',function (req, res, next) { var body = req.body; co(function *() { try { var user = yield User.findOneAndUpdate({ email: body.email }, { $set: {password: body.password} }); if (!user) { user = yield User.create(body); } res.send({ user: user }) } catch (e) { if (err && err.name === 'ValidationError') { return res.status(400).send(err) } else if (err) { return res.status(500).send(err) } } }); }); Co
  • 13. Using Co you can yield: Thunks (will be deprecated) Arrays co(function* () { // parallel var res = yield [ Promise.resolve(1), Promise.resolve(2), Promise.resolve(3), ]; console.log(res); // => [1, 2, 3] }).catch(onerror); Generators function* greet() { return yield new Promise((resolve, rej) => { resolve("Hello, Mary!") }); } co(function *(){ var greeting = yield greet console.log(greeting) }).catch((err) => { console.log(err) }); Promises
  • 14. Co
  • 15. Along with co will be useful: ◉mz - promisify NodeJS core modules ◉Thenify promisify any callback-based function var fs = require('mz/fs') fs.exists(__filename).then(function (exists) { if (exists) // do something }) var thenify = require('thenify'); var somethingAsync = thenify(function somethingAsync(a, b, c, callback) { callback(null, a, b, c); });
  • 16. Adopted by community Callbacks Async Promises Generators (along with co)
  • 17. Meet Koa! Philosophically, Koa aims to "fix and replace node", whereas Express "augments node"
  • 18. Koa Hello world var koa = require('koa'); var app = koa(); app.use(function *() { this.body = 'Hello World'; }); app.listen(3000);
  • 19. Koa API koa Request CONTEXT this.request this.response koa Response this.query this.url this.headers this.get - get a header this.body this.type - get content-type this.redirect this.status this.set -set a header
  • 20. app.use(function *(next) { var start = new Date; // <<<------ 1 yield next; // waits for downstream middlewares var delta = Math.ceil(Date.now() - start); // <<<------ 3 console.info(`${this.method} ${this.url} - ${delta}ms`); this.set('X-Response-Time', delta + 'ms'); // <<<------ 4 }); app.use(function *() { this.body = yield new Promise.resolve([10000]); // <<<------ 2 }); Response time - Koa middleware 3 4 2 1
  • 21. Custom error app.use(function *(next) { try { yield next; } catch (e) { if (e instanceof AuthError) { this.statusCode = e.status; this.redirect('/not-authorized'); this.body = this.render('not-authorized'); } else if (e.status) { this.statusCode = e.status; this.body = this.render('error', e); } else { this.statusCode = 500; this.body = this.render('error', e); logger.error('Unexpected error: ', e); // winston } } }); app.use(function *(next) { throw new AuthError() });
  • 22. app.post('/',function (req, res, next) { var body = req.body; if (!body.name || !body.email || !body.password) { return res.status(400).send("Missing username or email or password") }; // case #1- if user was registered (socials platform) before -> just add a password; User.findOneAndUpdate({ email: body.email }, { $set: {password: body.password} }, (err, user) => { if (err) return res.status(500).send(err) if (!user) { // case #2 - user has never been registering before -> create new one; User.create(body, (err, user) => { if (err && err.name === 'ValidationError') { return res.status(400).send(err) } else if (err) { return res.status(500).send(err) } return res.send({ user: user }) }); } else { return res.send({ user: body }) } }); }); Do you remember this example with callbacks?
  • 23. app.use(function *(next) { try { yield next; } catch (e) { if (e.status) { // app error this.body = e.message; this.statusCode = e.status; } if else (e && e.name === 'ValidationError') { this.body = e; this.statusCode = 400; } else { // Internal server error this.body = "Oops!"; this.status = 500; } } }); Koa way app.use(function *(next) { var body = this.request.body; if (!body.name || !body.email || !body.password) { throw new Error("Missing username||email||password"); } var user = yield User.findOneAndUpdate({email: body.email}, { $set: {password: body.password} }); if (!user) user = yield User.create(body); this.body = { user: this.body }; }); 2nd middleware 1st middleware
  • 24.
  • 25. app.get('/', function (req, res, next) { var readStream = fs.createReadStream('text.txt'); readStream.pipe(res); readStream.on('error', () => { res.statusCode = 500; res.end('Server error has occurred!'); }); res.on('close', () => readStream.destroy()); }); Send a file app.use(function* (next) { this.body = fs.createReadStream('text.txt') }); Express/node Koa
  • 26. “ “Koa and express uses the same modules. We’ve refactored express into jshttp and pillarjs so that anyone else can make their own framework as well”
  • 27.
  • 28. Express & Koa similarities Same modules Accepts, content-type, cookie, fresh, content- disposition, on-finished, parseurl, type-is, vary, escape-html Modular Each feature is moved to a separate module. Minimalistic Contains only essential (core) modules (e.g. headers parsing). Same developers Koa was build by core developers of Express: TJ Holowaychuk and others
  • 30. Koa ◉ router ◉ bigger community ◉ needs domains to catch async errors ◉ close to node style ◉ a lot of outdated examples and tutorials Express vs ◉ better error handling with try catch ◉ nice async flow control (no cb hell) ◉ api is more stable; ◉ no build-in router ◉ smaller community ◉ support stream out of the box ◉ easy to understand source code; no monkey patching