Asynchronous JavaScript
Anssi Kinnunen (@anssikin)
Tech friday 22.01.2016
Asynchrony (programming):
“Refers to the occurrence of events independently of the main
program flow”
https://en.wikipedia.org/wiki/Asynchrony_(computer_programming)
JavaScript
● Event loop -based concurrency model
● Almost all I/O is non-blocking
● Single thread, ask runtime to perform operation, provide
callback and move on to other tasks
https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop
http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/
http://www.2ality.com/2014/09/es6-promises-foundations.html
JavaScript runtime
● Contains a message queue
● Each message is associated with a callback function
● $(‘.btn’).click((evt) => { … })
○ Click (external event) causes message to be queued
https://developer.mozilla.
org/en/docs/Web/JavaScript/EventLoop
http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-
http://www.2ality.com/2014/09/es6-promises-foundations.html
http://stackoverflow.com/a/14797071
JavaScript event loop
● Synchronously processes message queue
● Each message is processed completely before others
○ When callback returns, event loop continues
● window.setTimeout(cb, wait)
https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop
http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/
http://www.2ality.com/2014/09/es6-promises-foundations.html
function () {
console.log('this is the start');
window.setTimeout(() => {
console.log('this is a msg from call back');
});
console.log('this is just a message');
window.setTimeout(() => {
console.log('this is a msg from call back1');
}, 0);
console.log('this is the end');
}
JavaScript event loop
● Browser tab is controlled by a single process
● UI, other computations
● Blocking the event queue?
https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop
http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/
http://www.2ality.com/2014/09/es6-promises-foundations.html
Web Workers
● API designed to allow running scripts in background
threads
● Worker has separate message queue, event loop and
memory space, independent from originating thread
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/
// pi_calculator.js
let reportResult = (e) => {
let pi = computePiToSpecifiedDecimals(e.data);
postMessage(pi);
};
onmessage = reportResult;
// main code
let piWorker = new Worker(‘pi_calculator.js’);
let logResult = (e) => {
console.log(`PI: ${e.data}`);
};
piWorker.addEventListener(‘message’, logResult, false);
piWorker.postMessage(100000);
ES6: Promise
Promise
● Represents (‘proxy’) operation that hasn’t completed yet
● Promise is always in one of three states
○ Pending: result has not been computed, yet
○ Fulfilled: result was computed succesfully
○ Rejected: failure occurred during computation
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
http://www.2ality.com/2014/10/es6-promises-api.html
Promise
● Promise.all( [ ] ), Promise.race( [ ] )
● Chaining: then() and catch() return promises
○ Promise() -> then() -> then() -> catch()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
http://www.2ality.com/2014/10/es6-promises-api.html
let doHeavyCalculation = (a, b) => {
return new Promise((resolve, reject) => {
console.log('wait 2000ms');
window.setTimeout(() => {
resolve(a + b);
}, 2000);
});
};
doHeavyCalculation(4, 4).then((result) => {
return doHeavyCalculation(result, 2);
}).then((calculatedValue) => {
console.log(`the result is ${calculatedValue}`);
});
http://www.2ality.com/2014/10/es6-promises-api.html
// Node.js style async file reading
fs.readFile(‘config.json’, (error, text) => {
if (error) {
console.error(‘Error while reading config file’);
} else {
try {
let obj = JSON.parse(text);
console.log(JSON.stringify(obj, null, 4));
} catch (e) {
console.error(‘Invalid JSON in file’);
}
}
});
// Same functionality with promises
readFilePromisified(‘config.json’)
.then((text) => {
let obj = JSON.parse(text);
console.log(JSON.stringify(obj, null, 4));
})
.catch((reason) => {
console.error(`An error occurred ${reason}`);
});
ES7: Async/Await
const request = require('request');
function getQuote() {
return new Promise((resolve, reject) => {
let url = 'http://ron-swanson-quotes.herokuapp.com/v2/quotes';
request(url, (error, response, quote) => {
if (error) {
reject(error);
} else {
resolve(quote);
}
});
});
}
async function main() {
try {
let quote = await getQuote();
console.log(quote);
} catch (e) {
console.error(e);
}
}
main();
https://www.twilio.com/blog/2015/10/asyncawait-the-hero-javascript-deserved.html
AJAX
Asynchronous JavaScript and XML
AJAX
● Group of technologies for async web
○ HTML/CSS, XML/XSLT, DOM
● Data passed is usually JSON
XHR
XMLHttpRequest
let request;
// Old compatibility code, no longer needed.
if (window.XMLHttpRequest) { // Mozilla, Safari, IE7+ ...
request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE 6 and older
request = new ActiveXObject("Microsoft.XMLHTTP");
}
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status === 200) {
console.log(request.responseText);
}
}
request.open('GET', 'http://davidwalsh.name/ajax-endpoint', true);
request.send(null);
https://davidwalsh.name/xmlhttprequest
https://developer.mozilla.org/en-US/docs/AJAX/Getting_Started
$.get({
url: 'http://davidwalsh.name/ajax-endpoint',
success: function(response) {
console.log(response);
}
});
Fetch API
https://developer.mozilla.org/en/docs/Web/API/Fetch_API
Fetch
● Interface for fetching resources, not finalized yet
● Like XHR, but more powerful
● window.fetch() -> Promise() -> Response
// Chaining for more "advanced" handling
fetch('/some/url').then((response) => {
return //...
}).then((returnedValue) => {
// ...
}).catch((err) => {
// Error :(
});
https://www.twilio.com/blog/2015/10/asyncawait-the-hero-javascript-deserved.html

Tech friday 22.01.2016

  • 1.
    Asynchronous JavaScript Anssi Kinnunen(@anssikin) Tech friday 22.01.2016
  • 2.
    Asynchrony (programming): “Refers tothe occurrence of events independently of the main program flow” https://en.wikipedia.org/wiki/Asynchrony_(computer_programming)
  • 3.
    JavaScript ● Event loop-based concurrency model ● Almost all I/O is non-blocking ● Single thread, ask runtime to perform operation, provide callback and move on to other tasks https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/ http://www.2ality.com/2014/09/es6-promises-foundations.html
  • 4.
    JavaScript runtime ● Containsa message queue ● Each message is associated with a callback function ● $(‘.btn’).click((evt) => { … }) ○ Click (external event) causes message to be queued https://developer.mozilla. org/en/docs/Web/JavaScript/EventLoop http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop- http://www.2ality.com/2014/09/es6-promises-foundations.html
  • 5.
  • 6.
    JavaScript event loop ●Synchronously processes message queue ● Each message is processed completely before others ○ When callback returns, event loop continues ● window.setTimeout(cb, wait) https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/ http://www.2ality.com/2014/09/es6-promises-foundations.html
  • 7.
    function () { console.log('thisis the start'); window.setTimeout(() => { console.log('this is a msg from call back'); }); console.log('this is just a message'); window.setTimeout(() => { console.log('this is a msg from call back1'); }, 0); console.log('this is the end'); }
  • 8.
    JavaScript event loop ●Browser tab is controlled by a single process ● UI, other computations ● Blocking the event queue? https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/ http://www.2ality.com/2014/09/es6-promises-foundations.html
  • 9.
    Web Workers ● APIdesigned to allow running scripts in background threads ● Worker has separate message queue, event loop and memory space, independent from originating thread https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/
  • 10.
    https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/ // pi_calculator.js let reportResult= (e) => { let pi = computePiToSpecifiedDecimals(e.data); postMessage(pi); }; onmessage = reportResult; // main code let piWorker = new Worker(‘pi_calculator.js’); let logResult = (e) => { console.log(`PI: ${e.data}`); }; piWorker.addEventListener(‘message’, logResult, false); piWorker.postMessage(100000);
  • 11.
  • 12.
    Promise ● Represents (‘proxy’)operation that hasn’t completed yet ● Promise is always in one of three states ○ Pending: result has not been computed, yet ○ Fulfilled: result was computed succesfully ○ Rejected: failure occurred during computation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise http://www.2ality.com/2014/10/es6-promises-api.html
  • 13.
    Promise ● Promise.all( [] ), Promise.race( [ ] ) ● Chaining: then() and catch() return promises ○ Promise() -> then() -> then() -> catch() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise http://www.2ality.com/2014/10/es6-promises-api.html
  • 14.
    let doHeavyCalculation =(a, b) => { return new Promise((resolve, reject) => { console.log('wait 2000ms'); window.setTimeout(() => { resolve(a + b); }, 2000); }); }; doHeavyCalculation(4, 4).then((result) => { return doHeavyCalculation(result, 2); }).then((calculatedValue) => { console.log(`the result is ${calculatedValue}`); });
  • 15.
    http://www.2ality.com/2014/10/es6-promises-api.html // Node.js styleasync file reading fs.readFile(‘config.json’, (error, text) => { if (error) { console.error(‘Error while reading config file’); } else { try { let obj = JSON.parse(text); console.log(JSON.stringify(obj, null, 4)); } catch (e) { console.error(‘Invalid JSON in file’); } } }); // Same functionality with promises readFilePromisified(‘config.json’) .then((text) => { let obj = JSON.parse(text); console.log(JSON.stringify(obj, null, 4)); }) .catch((reason) => { console.error(`An error occurred ${reason}`); });
  • 16.
  • 17.
    const request =require('request'); function getQuote() { return new Promise((resolve, reject) => { let url = 'http://ron-swanson-quotes.herokuapp.com/v2/quotes'; request(url, (error, response, quote) => { if (error) { reject(error); } else { resolve(quote); } }); }); } async function main() { try { let quote = await getQuote(); console.log(quote); } catch (e) { console.error(e); } } main(); https://www.twilio.com/blog/2015/10/asyncawait-the-hero-javascript-deserved.html
  • 18.
  • 19.
    AJAX ● Group oftechnologies for async web ○ HTML/CSS, XML/XSLT, DOM ● Data passed is usually JSON
  • 20.
  • 21.
    let request; // Oldcompatibility code, no longer needed. if (window.XMLHttpRequest) { // Mozilla, Safari, IE7+ ... request = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE 6 and older request = new ActiveXObject("Microsoft.XMLHTTP"); } request.onreadystatechange = () => { if (request.readyState === 4 && request.status === 200) { console.log(request.responseText); } } request.open('GET', 'http://davidwalsh.name/ajax-endpoint', true); request.send(null); https://davidwalsh.name/xmlhttprequest https://developer.mozilla.org/en-US/docs/AJAX/Getting_Started
  • 22.
  • 23.
  • 24.
    https://developer.mozilla.org/en/docs/Web/API/Fetch_API Fetch ● Interface forfetching resources, not finalized yet ● Like XHR, but more powerful ● window.fetch() -> Promise() -> Response
  • 25.
    // Chaining formore "advanced" handling fetch('/some/url').then((response) => { return //... }).then((returnedValue) => { // ... }).catch((err) => { // Error :( }); https://www.twilio.com/blog/2015/10/asyncawait-the-hero-javascript-deserved.html