by Rob Richardson
Rob Richardson is a software craftsman building web properties in ASP.NET and Node, Angular and Vue. He's a frequent speaker at conferences, user groups, and community events, and a diligent teacher and student of high quality software development. You can find this and other talks on https://robrich.org/presentations and follow him on twitter at @rob_rich.
Do things in parallelsource: http://benhoff.net/qt-interface-design.html |
Yield while I'm waitingsource: https://itxdesign.com/vps-vs-shared-hosting/ |
In the beginning ...
callLib(inp, args, function (err, res, ults) {
if (err) {
// handle error
return;
}
// handle success
});
The nested wing
callLib(req, function (err, res1) {
if (err) {
return handle(err);
}
callLib(function (err, res2) {
if (err) {
return handle(err);
}
callLib(function (err, res3) {
if (err) {
return handle(err);
}
callLib(function (err, res4) {
if (err) {
return handle(err);
}
done(res1, res2, res3, res4);
});
});
});
});
Pros
|
Cons
|
callLib1(inp, args)
.then(r => callLib2(r))
.then(done)
.catch(handleError);
function callLib1(inp, args) {
// all evergreen browsers, since Node 6
return new Promise(function (resolve, reject) {
// do stuff
if (err) {
return reject(err);
}
resolve(answer);
});
}
return
wraps in promise
callLib1(inp, args)
.then(function (r1) {
return new Promise((resolve, reject) => {
resolve(r1);
});
})
.then(function (r2) {
return r2;
})
.then(done)
.catch(handleError);
Pros
|
Cons
|
async
& await
async
& await
Clearly stolen inspired by C#
Identical syntax to C#
Under the hood, it's promises and generators
Think: resumable state machine
async
& await
async function myFunc() {
try {
// all evergreen browsers, since Node 7.6
let p1 = await callLib1(inp, args);
let p2 = await callLib2(inp, args);
let p3 = await callLib3(inp, args);
return { p1, p2, p3 };
} catch (err) {
handleError(err);
}
}
async
& await
throw
is easyasync function lib(inp, arg) {
if (!inp) {
throw new Error('inp is blank');
}
let res = await longRunningTask();
return res;
}
async
& PromisePromise calls async fn
// lib.js
async function callLib(inp, arg) {
if (!inp) {
throw new Error('inp is blank');
}
let res = await longRunningTask();
return res;
}
// main.js
callLib(inp, arg)
.then(res => done(res))
.catch(errorHandler);
async
& Promiseawait a Promise
// lib.js
function callLib(inp, arg) {
return new Promise((resolve, reject) => {
resolve(true);
});
}
// main.js
async function () {
try {
let res = await callLib(inp, arg);
return res;
} catch (err) {
handleError(err);
}
}
Source: https://www.bram.us/2017/05/09/javascript-from-callbacks-to-promises-to-asyncawait-in-7-seconds/
built-in util module
const promisify = require('util').promisify;
const newfn = promisify(callbackfn);
newfn(...)
.then(...)
.catch(...);
doesn't follow convention
// BROKEN:
const promisify = require('util').promisify;
const sleep = promisify(setTimeout);
// can't do it, setTimeout doesn't follow convention
const sleep = function(timeout) {
return new Promise(resolve => setTimeout(resolve, timeout));
}
// ...
await sleep(100);
// ...
const sleep = timeout => new Promise(resolve => setTimeout(resolve, timeout));
const sleep = function(timeout) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve();
}, timeout);
}
};
promisify
and callbackify
Pros
|
Cons
|
// routes/index.js
const express = require('express');
const router = express.Router();
router.get('/', function(req, res) {
// TODO: async stuff
res.render('index');
});
module.exports = router;
// app.js
// ...
const index = require('./routes/index');
app.use('/path', index);
// ...
router.get('/', async function(req, res) {
const result = await asyncStuff(arg);
res.render('index');
});
router.get('/', function(req, res, next) {
asyncStuff(arg, function (err, result) {
if (err) {
return next(err);
}
res.render('index');
});
});
async
Pros |
Cons
|
async
func