The following summarises the learnings of migrating from the async
promises module to ES6 promises
, with a simple sample.
Async
is a library containing a bunch of async utility functions like
async.parallel
: To execute a bunch of async tasks in parallel.async.waterfall
: To execute a bunch of async tasks sequentially.
####The example had a combo of both:
The example below uses an express APP to create a server & uses the Async JS module with it.
var app = express();
Async.waterfall([
Async.parallel.bind(Async, {
init: function initStartup(next) {
app.once('start', function () {
next();
});
},
config: function loadConfig(next) {
//> read entries from a config file
require('./src/config').onConfigured(function (config) {
next(null, config);
});
}
}),
function start(ctx, next) {
listen(ctx.config, next);
}
], function started() {
if (process.send) {
process.send('online');
}
console.log('Server ready');
});
function listen(config, next) {
var tasks = [];
//> app uses Kraken JS
var ssl = app.kraken.get('ssl');
//Running HTTPS server on 8443 in Development Env
if(ssl && env.isDev()) {
tasks.push(function startSSL(next) {
var sslServer = https.createServer(ssl, app);
sslServer.listen(process.env.SSLPORT || 8443, function () {
console.log('Application(HTTPS) Listening on port ', sslServer.address().port);
next();
});
});
} else {
//Running additional port 8082 in Non-DEV
tasks.push(function startSSL(next) {
var sslport = process.env.SSLPORT || 8082;
app.listen(sslport, function () {
console.log('Application(HTTP) Listening on port ' + sslport);
next();
});
});
}
tasks.push(function startNonSSL(next) {
// non-secure port
var port = config.port;
app.listen(port, function () {
console.log('Application(HTTP) Listening on port ' + port);
next();
});
});
Async.parallel(tasks, next);
}
The above code in ES6 becomes:
The above piece of code is re-written in ES6 makes use of
- ES6 Promises,
- const,
- Block Scoping,
- usage of let for block scoping &
- ES6 Arrow functions that replace Anonymous functions
var app = express();
//> wrapping an async Task within a new Promise() - ES6 feature
var asyncTask_1 = new Promise((resolve, reject) => {
//> promise is in pending state until it gets resolved within this block
app.once('start', () => {
//> just resolving it with a param
resolve('success');
});
});
//> wrapping an async Task within a new Promise() - ES6 feature
var asyncTask_2 = new Promise((resolve, reject) => {
//> promise is in pending state until it gets resolved within this block
require('./src/config').onConfigured((config) => {
resolve(config);
});
});
//> execute the two above mentioned async Tasks in parallel, but do sequential operations after both are resolved - ES6 feature
//> Promise.all - equivalent of Async.parallel - ES6 feature
//> every .then() following this is a sequential task. It takes a param called values which is an array of results
//> - equivalent of Async.waterfall
Promise.all([asyncTask_1, asyncTask_1])
.then(
(values) => { //> success handler of then
//> upon success of previous parallel tasks, do the next sequential async task
//> Even for this async Task, the promise is in pending state until it gets resolved within this block
new Promise((resolve, reject) => {
//> result2 contains the result of asyncTask_2
//> promise resolution for the current promise, happens in listen
listen(values[1], resolve, reject);
});
},
(error) => { //> failure handler of then
console.log(error);
//> promise resolution is done instantaneously to reject for error
//> if not rejected, it will not progress in case of an error
new Promise((resolve, reject) => {
reject();
});
}
).then(
(values) => { //> success handler for then
if (process.send) {
process.send('online');
}
console.log('Server ready');
},
(error) => { //> failure handler for then
console.log(error);
}
);
//> re-writing listen() in ES6
function listen(config, resolve, reject) {
//> define a constant - ES6 feature
//> app uses Kraken JS
const ssl = app.kraken.get('ssl');
//> define a block scope - ES6 feature
{
let async_1; // block scope variable - ES6 feature
//> Running HTTPS server on 8443 in Development Env
if (ssl && env.isDev()) {
//> Async operation wrapped in a promise
async_1 = new Promise((resolve, reject) => {
const sslServer = https.createServer(ssl, app);
sslServer.listen(process.env.SSLPORT || 8443, () => {
console.log('Application(HTTPS) Listening on port ', sslServer.address().port);
resolve();
});
});
} else {
//> Running additional port 8082 in Non-DEV
//> Async operation wrapped in a promise
async_1 = new Promise((resolve, reject) => {
const sslport = process.env.SSLPORT || 8082;
app.listen(sslport, () => {
console.log('Application(HTTP) Listening on port ' + sslport);
resolve();
});
});
}
//> block scoped variable containing an async operation wrapped in a promise
let async_2 = new Promise((resolve, reject) => {
// non-secure port
const port = config.port;
app.listen(port, () => {
console.log('Application(HTTP) Listening on port ' + port);
resolve();
});
});
//> execute all async operations in parallel - equivalent of Async.parallel
//> Get their values, if the success block is invoked,
//> resolve the caller
Promise
.all([async_1, async_2])
.then(
(values) => {
resolve(); //> using the arguments resolve - that was passed into listen()
},
(error) => {
console.log(error);
reject(); //> using the arguments reject - that was passed into listen()
}
); //> end of then
} //> end of block scope
} //> end of listen()