OdessaJs conference 2016, better quality presentation: https://goo.gl/SQjwod
Speaker: Kozhukharenko Nikolay, K&C;
Topic: "Koajs as an alternative to Express"
Content:
- Why Koajs is the better version of Express?
- What is es6 js generators?
- How to use generators to write errorless code in NodeJS
- Asynchronous code in synchronous manner with tj/co library;
- Comparison of KoaJs and Express, similarities and differences
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
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);
});
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
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