-
Async JS Pattern
- Write Promises/callback/async-await/generators/observables/async events


Async Node Pattern
What is async
events
callback
stream
xhr
I/O
doThing('value', (err, result) => {
if (err) {
// handle error here
console.error(err);
} else {
// handle success here
console.log(result);
}
});
callback
for (var i = 0; i < 100; i++) {
(function (i) {
setTimeout(function () {
console.log(i);
}, 100);
})(i);
// The current value of
//i is captured by self executing function
}
console.log('this still gets printed first.');
basic async in a loop
Promises
doThing('value')
.then(value => {
// handle success here
console.log(value);
})
.catch(reason => {
// handle error here
console.error(reason);
});
Promises chaining 1-2-3-4...
asyncCount()
.then(function(count){
console.log(count); //1
return asyncCount();
})
.then(function(){
throw
new Error("Oops an error occurred");
})
.then(function(){
return asyncCount();
})
.then(function(res){/*wont be called*/}, function (err){
console.log(err.message);
//Oops an error occurred ...
}).catch((err) => {
})
try {
const result = await doThing('value');
// handle success here
console.log(result);
} catch (ex) {
// handle error here
console.error(ex);
}
Async await
async function myFunction(inputValue) {
try {
const a = await asyncFunc1('value');
const b = await asyncFunc2(a);
const c = syncFunc3(b);
return await asyncFunc4(c);
} catch (ex) {
// handle exception
}
}
Code like a king !!
function* formatAnswer() {
const answer = yield 'foo';
return `The answer is ${ answer }`;
}
const generator = formatAnswer();
console.log(generator.next());
// {value: "foo", done: false}
console.log(generator.next(42));
// {value: "The answer is 42", done: true}
Generators **
async function main () {
const [user, product] = await Promise.all([
Users.fetch(userId),
Products.fetch(productId)
])
await makePurchase(user, product)
}
async await running things parallel ---level 2
async.waterfall(
[
(cb) => {
cb(null, solution[0]);
},
(solution, cb) => {
cb(null, pGetTree, solution);
},
(pGetTree, solution, cb) => {
cb(null, tempPGetTree);
}
],
);
});
}
Waterfall using Async
Handling Rejections !!
async function main () {
await new Promise((resolve, reject) => {
reject(new Error('đź’Ą'))
})
}
main()
.then(console.log)
Handling Rejections proper way !!
const util = require('util')
async function main () {
try {
await new Promise((resolve, reject) => {
reject(new Error('đź’Ą'))
})
} catch (err) {
// handle error case
// maybe throwing is okay depending on your use-case
}
}
main()
.then(console.log)
.catch(console.error)
I know promises only !!
const util = require('util')
const {readFile} = require('fs')
const readFileAsync = util.promisify(readFile)
async function main () {
const result = await readFileAsync('.gitignore')
return result
}
main()
.then(console.log)
.catch(console.error)

Preventing HTTP Parameter Pollution (HPP)
var hpp = require('hpp');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
//body parser should be placed before using hpp
app.use(hpp());
app.get('/', function(req, res, next){
console.log('Query Parameters : ' + JSON.stringify(req.query));
console.log('Polluted Query Parameters : '+ JSON.stringify(req.queryPolluted));
res.render('index');
});
Setting Security Response Headers
var express = require('express');
var app = express();
app.disable('x-powered-by'); // disable X-Powered-By header
app.use(function(req, res, next){
res.header('X-XSS-Protection', '1; mode=block');
res.header('X-Frame-Options', 'deny');
res.header('X-Content-Type-Options', 'nosniff');
next();
});
Setting Security Response Headers
- X-Frame-Options — Prevents your application being displayed in iframes
- X-XSS-Protection — Invokes browser XSS protection mechanisms
- X-Content-Type-Options — Prevents mime sniffing
Setting Security Response Headers
var helmet = require('helmet');
app.use(helmet.hidePoweredBy({setTo: 'DummyServer 1.0'}));
//change value of X-Powered-By header to given value
app.use(helmet.noCache({noEtag: true}));
//set Cache-Control header
app.use(helmet.noSniff());
// set X-Content-Type-Options header
app.use(helmet.frameguard());
// set X-Frame-Options header
app.use(helmet.xssFilter());
// set X-XSS-Protection header
NPM Modules
- csurf — Implement Anti-CSRF tokens to prevent cross site request forgery
- cors — Enable Cross origin resource sharing
- hpp — Protection from HTTP Parameter Pollution
- express-content-length-validator — Prevent DOS attacks
- rate-limiter — Prevent DOS attacks
- helmet — Set custom security headers
- nsp — Scan for deprecated/vulnerable npm modules used in your app
- retire — Scan for deprecated/vulnerable npm modules used in your app
- mocha, should, supertest — Writing node.js tests
-
bunyan — Logging
Use explicit package versions
{
"name": "My App",
"version": "0.0.0",
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"express": "~4.13.1",
"http-auth": "~2.2.8",
"jade": "~1.11.0",
"jsonfile": "~2.2.1",
"morgan": "~1.6.1",
"nodemon": "~1.4.1",
"serve-favicon": "~2.3.0"
}
}
No sensitive data inside your repo !!!
app.use(session({
name: 'SESS_ID',
secret: process.env.EXPRESS_SESSION_SECRET,
resave: false,
saveUninitialized: true,
cookie: {
secure: true,
httpOnly: true
}
}));
always keep your application components up-to-date. Following are few tools that you can use to identify potential outdated components in your application.
And also keep your Node.js version and NPM up to date. Node.js version can be updated with “n”
sudo npm install n sudo n stable
You can update
sudo npm install -g npm
Can we, effectively, build a program using this notion?
Meet your new friend:
 The Observable
Your friendly neighbor: RxJS
Reactive Extensions
Are a set of libraries for composing asynchronous and event-based programs using observable sequences and fluent query operators
Rx is everywhere

Java
JavaScript
.Net
Ruby
Swift
C++
Clojure
Scala
What is the most asynchronous?
User





More async data streams
-
XHR requests
-
WebSocket
-
Promises
-
Events
-
Dom Inputs
-
Web Worker
-
Web RTC
RxJS operators
RxJS operators
RxJS operators: map

resStream
RxJS operators: delay

resStream
RxJS operators: debounce

resStream
RxJS operators: merge

resStream
RxJS operators: combineLatest

resStream
RxJS operators: zip

resStream
Let's create a morse-code decoder!
Morse-code decoder

click...
click...
click.............
click...
Morse-code decoder
click...
click...
click.............
click...
Morse-code decoder
-
Dom events (keydown, keyup)
-
Start signal/End signal
-
Dot/Dash/Whitespace
-
Letter
-
Word/Sentence
Morse-code decoder

Morse-code decoder
-
"." = ~400ms
-
"_" = 3 * "."
-
between codes = "."
-
between letters = 3 * "."Â
-
between words = 7 * "."

Morse-code decoder
const keyUps = Rx.Observable
.fromEvent(document, 'keyup');
const keyDowns = Rx.Observable
.fromEvent(document, 'keydown');
Morse-code decoder
const spaceKeyUps = keyUps.filter((data) => data.keyCode === 32);
const spaceKeyDowns = keyDowns.filter((data) => data.keyCode === 32);

Morse-code decoder
const signalStartsRaw = spaceKeyDowns.map(() => "start");
const signalEndsRaw = spaceKeyUps.map(() => "end");
const signalStartsEnds = Rx.Observable
.merge(signalStartsRaw, signalEndsRaw)
.distinctUntilChanged();

Morse-code decoder
const signalStarts = signalStartsEnds
.filter((ev) => ev === "start")
.timestamp();
const signalEnds = signalStartsEnds
.filter((ev) => ev === "end")
.timestamp();
const spanStream = signalStarts.flatMap((start) => {
return signalEnds.map((end) => end.timestamp - start.timestamp)
.first();
});
Morse-code decoder

Morse-code decoder
const SPAN = 400;
const dotsStream = spanStream
.filter((v) => v <= SPAN)
.map(() => ".");
const lineStream = spanStream
.filter((v) => v > SPAN)
.map(() => "-");
Morse-code decoder
const dotsAndLines = Rx.Observable.merge(dotsStream, lineStream);
// [['.', '.', '-'], ['-', '.', '-'] ... ]
const letterCodes = dotsAndLines.buffer(letterWhitespaces);
// ['A', 'B' ...]
const lettersStream = letterCodes
.map((codes) => morse.decode(codes.join("")));
Morse-code decoder

demo — http://alexmost.github.io/morse/
source — https://github.com/AlexMost/morse
Morse-code decoder

What else?
Component bindings

Component bindings
click...
click...
click.............
click...
click
category.
comp.
bundle.
package.
Component bindings

Component bindings

Problems RxJSÂ solves
-
Data Manipulation
-
Events handling
-
Callback Hell
-
Promise Hell
-
Comet/Async Manipulation
-
Race Conditions
-
Complex State
-
TestsÂ

RxJS problems
Complexity

Integration with imperative part of code

Documentation
Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences or Promises or array/iterable into one observable sequence.
Cascade Updating
Cascade Updating
Cascade Updating/Exceptions
RxJS with other frameworks
RxJS with Angular - rx.angular.js
angular.module('example', ['rx'])
.controller('AppCtrl', function($scope, $http, rx) {
function searchWikipedia (term) {
return rx.Observable
.fromPromise($http({}))
.map(function(response){ return response.data[1]; });
}
$scope.search = '';
$scope.results = [];
$scope.$createObservableFunction('click')
.map(function () { return $scope.search; })
.flatMapLatest(searchWikipedia)
.subscribe(function(results) {
$scope.results = results;
});
});
RxJS with Angular2 - inside

RxJS with React - rx-react

RxJS with others







Alternative?
Bacon

Kefir

Highland
I want more hardcore!
Javelin and ClosureScript
(defc test-results
{:scores [74 51 97 88 89 91 72 77 69 72 45 63]
:proctor "Mr. Smith"
:subject "Organic Chemistry"
:sequence "CHM2049"})
(defc= test-results-with-mean
(let [scores (:scores test-results)
mean (/ (reduce + scores) (count scores))
grade (cond (<= 90 mean) :A
(<= 80 mean) :B
(<= 70 mean) :C
(<= 60 mean) :D
:else :F)]
(assoc test-results :mean mean :grade grade)))
Cycle.js
-
RxJS
-
Side effects/Logic
-
Composition
-
Streams, streams, streams, streams

Questions?
node js security webinar 02
By Tarun Sharma
node js security webinar 02
- 645