├── .gitignore ├── README.md ├── handler ├── async.js ├── await.js ├── callback.js ├── generator.js ├── index.js └── promise.js ├── index.js ├── package.json ├── server.js └── util.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Article](https://blog.risingstack.com/node-js-async-best-practices-avoiding-callback-hell-node-js-at-scale/) examples to handle async for the Node.js at Scale series. 2 | 3 | Read more: https://blog.risingstack.com 4 | -------------------------------------------------------------------------------- /handler/async.js: -------------------------------------------------------------------------------- 1 | const async = require('async') 2 | const promisify = require('es6-promisify') 3 | const { fastAsyncFunction, asyncFunction, slowAsyncFunction } = require('../util') 4 | 5 | function handler (done) { 6 | async.series([ 7 | fastAsyncFunction, 8 | asyncFunction, 9 | slowAsyncFunction 10 | ], done) 11 | } 12 | 13 | module.exports = promisify(handler) 14 | -------------------------------------------------------------------------------- /handler/await.js: -------------------------------------------------------------------------------- 1 | const { fastAsyncFunctionPromise, asyncFunctionPromise, slowAsyncFunctionPromise } = require('../util') 2 | 3 | async function handler () { 4 | await fastAsyncFunctionPromise() 5 | await asyncFunctionPromise() 6 | await slowAsyncFunctionPromise() 7 | } 8 | 9 | module.exports = handler 10 | -------------------------------------------------------------------------------- /handler/callback.js: -------------------------------------------------------------------------------- 1 | const promisify = require('es6-promisify') 2 | const { fastAsyncFunction, asyncFunction, slowAsyncFunction } = require('../util') 3 | 4 | function handler (done) { 5 | fastAsyncFunction((err) => { 6 | if (err) return done(err) 7 | asyncFunction((err) => { 8 | if (err) return done(err) 9 | slowAsyncFunction((err) => { 10 | done(err) 11 | }) 12 | }) 13 | }) 14 | } 15 | 16 | module.exports = promisify(handler) 17 | -------------------------------------------------------------------------------- /handler/generator.js: -------------------------------------------------------------------------------- 1 | const co = require('co') 2 | const { fastAsyncFunctionPromise, asyncFunctionPromise, slowAsyncFunctionPromise } = require('../util') 3 | 4 | function * handler () { 5 | yield fastAsyncFunctionPromise() 6 | yield asyncFunctionPromise() 7 | yield slowAsyncFunctionPromise() 8 | } 9 | 10 | module.exports = co.wrap(handler) 11 | -------------------------------------------------------------------------------- /handler/index.js: -------------------------------------------------------------------------------- 1 | const callback = require('./callback') 2 | const async = require('./async') 3 | const promise = require('./promise') 4 | const generator = require('./generator') 5 | const await = require('./await') 6 | 7 | module.exports = { 8 | callback, 9 | async, 10 | promise, 11 | generator, 12 | await 13 | } 14 | -------------------------------------------------------------------------------- /handler/promise.js: -------------------------------------------------------------------------------- 1 | const { fastAsyncFunctionPromise, asyncFunctionPromise, slowAsyncFunctionPromise } = require('../util') 2 | 3 | function handler (params) { 4 | return fastAsyncFunctionPromise() 5 | .then(() => asyncFunctionPromise()) 6 | .then(() => slowAsyncFunctionPromise()) 7 | } 8 | 9 | module.exports = handler 10 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('./server.js') 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rs-blog-scale-async", 3 | "version": "1.0.0", 4 | "engines": { 5 | "node": "7.4.0" 6 | }, 7 | "description": "Article examples to handle async for the Node.js at Scale series", 8 | "main": "index.js", 9 | "scripts": { 10 | "dev": "node --harmony-async-await index.js", 11 | "dev:watch": "nodemon --harmony-async-await index.js" 12 | }, 13 | "author": "RisingStack Inc.", 14 | "license": "ISC", 15 | "dependencies": { 16 | "async": "2.1.4", 17 | "co": "4.6.0", 18 | "es6-promisify": "5.0.0", 19 | "express": "4.14.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const handler = require('./handler') 3 | const app = express() 4 | 5 | app.get('/test/:example', function (req, res, next) { 6 | const example = req.params.example 7 | const label = `Handler (${example})` 8 | 9 | console.time(label) 10 | 11 | handler[example]() 12 | .then((result) => res.send(result)) 13 | .catch(next) 14 | .then(() => { 15 | console.timeEnd(label) 16 | }) 17 | }) 18 | 19 | app.listen(3000, function () { 20 | console.log('Examples:') 21 | console.log(['callback', 'async', 'promise', 'generator', 'await'] 22 | .map((example) => `http://localhost:3000/test/${example}`)) 23 | }) 24 | -------------------------------------------------------------------------------- /util.js: -------------------------------------------------------------------------------- 1 | const promisify = require('es6-promisify') 2 | 3 | function fastAsyncFunction (done) { 4 | console.time('fastAsyncFunction') 5 | setTimeout(() => { 6 | console.timeEnd('fastAsyncFunction') 7 | done() 8 | }, 100) 9 | } 10 | 11 | function asyncFunction (done) { 12 | console.time('asyncFunction') 13 | setTimeout(() => { 14 | console.timeEnd('asyncFunction') 15 | done() 16 | }, 500) 17 | } 18 | 19 | function slowAsyncFunction (done) { 20 | console.time('slowAsyncFunction') 21 | setTimeout(() => { 22 | console.timeEnd('slowAsyncFunction') 23 | done() 24 | }, 1000) 25 | } 26 | 27 | const fastAsyncFunctionPromise = promisify(fastAsyncFunction) 28 | const asyncFunctionPromise = promisify(asyncFunction) 29 | const slowAsyncFunctionPromise = promisify(slowAsyncFunction) 30 | 31 | module.exports = { 32 | fastAsyncFunction, 33 | asyncFunction, 34 | slowAsyncFunction, 35 | fastAsyncFunctionPromise, 36 | asyncFunctionPromise, 37 | slowAsyncFunctionPromise 38 | } 39 | --------------------------------------------------------------------------------