ASYNCHRONOUS JAVASCRIPT

Hi I`m Viktor

  • Love building User Interactions
  • Frontend developer in GlobalLogic
  • Freelancer in past...

vict.shevchenko@gmail.com
@vict_shevchenko

Agenda

  • What is asynchronous code?
  • How to write async code in JS?
  • Why promises?
  • History
  • Promises in JavaScript
  • Promises Now
  • Promises in your code
  • Generators / Yields (ES6)
  • Async / Await (ES7)

Asynchronous is...

  • Not synchronized
  • The order of operation results may differ from order operations were initiated
//sync

function a () { // returns 'a' }
function b () { // returns 'b' }
function c () { // returns 'c' }

a();
b();
c();

// a
// b
// c
//async

function a () { // returns 'a' }
function b () { // returns 'b' }
function c () { // returns 'c' }

a();
b();
c();

// a
// c
// b

Why we want to use it at all?

There are operatios

We can`t predict how long they will take, and whether they will be finished?

For Example...

  • Network (Ajax)
  • I/O
  • Database
  • File System
  • etc.

So what will happen if we will run  them synchronous?

Use async when...

You need to provide non blocking UI in a JavaScript single thread environment

But we also have...

And finally...

  • We have long running operations
  • Running them synchronous will block UI
  • Lets use async functions!!!
  • But BL says - "function c should start only after async function b"
  • If b is async, how to determine when it is fulfilled?
  • Lets learn of how to write async code!

How to write async code?

  • Event loop
  • Callback
  • Promise
  • Generators
  • Async/Await

Event Loop

console.log('hello'); //a

setTimeout(function () {
    console.log('to Lviv'); //b
}, 1000);

console.log('from Kyiv') //c

//hello
//from Kyiv
//to Lviv

Event Loop

is powerful but tricky...

setTimeout(function () {
    console.log('hello Lviv');
}, 1000);

for(var i = 0; i < 100000000; i++) {
    //calculate Fibonacci ~5sec
}

//hello Lviv (after much more than 1sec)
console.time('test');

setTimeout(function() {
    console.log(console.timeEnd('test'));
}, 0);

// test: 4.319ms

Callback

function getY() {
    var y;

    $.get('get/y', function(result) {
        y = result;
    });

    return y;
}

var x = 10;
var y = getY();

console.log(x + y);

// NaN

Why it does not work?

Callback

Because JS allows to to pass functions as a parameters, we can wrap a code in a callback

function getY(callback) {
    var y;

    $.get('get/y', function(result) {
        y = result; //5
        callback(y);
    });
}

var x = 10;

getY(function(y) {
    console.log(x + y);
});

//15

Callback issues

  • Doing thing in sequence is hard
  • Errors get lost easily
  • Error handling should be in every callback
  • Easy to lose flow

Callback Hell

function updateStoryComment(id) {
    $.get({
        url: 'get/story/id',
        success: function (story){
            $.get({
                url: 'get/story/comment/:id',
                success: function (comment) {
                    asyncUserDialog(function (updatedText) {
                        $.post({
                            url: 'post/story/comment/id',
                            data: updatedText,
                            success: function () {
                                notifyUser();
                            }
                        });
                    });
                }
            });
        }
    });
}


updateStoryComment(12);

Instead of passing a callback return a promise

Ok, so what is promise?

WIKI: In computer science, future, promise, and delay refer to constructs used for synchronizing in some concurrent programming languages. They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is yet incomplete.

Abstraction over asynchronous code

Utility on callback aggreagation

Promise Basics

function asyncSum(a, b) {
    var promise = new Promise();
    
    setTimeout(function() {
        promise.resolve(a + b);
    }, 1000);
    
    return promise;
}

function () {
    var asyncResult = asyncSum(3,5);
    
    asyncResult.then(function (result) {
        console.log(result);  
    
    asyncResult.catch(function (error) {
        console.log(error);  

    asyncResult.finally(function (error) {
        console.log("Fully Done Now");  
}

Library usage

Promise Basics

function asyncSum(a, b) {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve(a + b);
    }, 1000);
  });
}

var asyncResult = asyncSum(3,5); // returned result is promise object

asyncResult.then(function (result) {
    console.log(result);  //logs 8 after more that 1000ms
});

Native usage

Chaining and Error Handling

function updateStoryComment(id) {
    fetch('get/story/id')
    .then(function (story) {
        return fetch('get/story/comment/id');
    })
    .then(asyncUserDialog())
    .then(function (updatedText) {
        return fetch('get/story/comment/id', method: 'POST', body: updatedText);
    })
    .then(function () {
        notifyUser();
     })
    .catch(handleErrorDuringUpdating());
}

updateStoryComment(12);

The point is simple

Provide you with async version of return and throw

var result, exception = false;

try {
    result = doSomethingSync();
} catch (ex){
    exception = ex;
    handle(exception)
}

if(!exception) {
    return result;
}
doSomethingAsync()
    .then(processResult, handleException);

Sync

Async

Why promises are awesome

  • cleaner method signatures(.then(success(), error()))
  • uniform return/trow exception semantic
  • easy composition
  • easy sequential/parallel join
  • always async
  • exception style error bubbling

Promise history

The term promise was proposed in 1976 by Daniel P. Friedman and David Wise, and Peter Hibbard called it eventual. A somewhat similar concept future was introduced in 1977 in a paper by Henry Baker and Carl Hewitt.

Promise history

  • The term promise was coined by Arbara Liskov and Liuba Shrira in 1988
  • The future and/or promise constructs were first implemented in programming languages such as MultiLisp and Act 1. ca. 1989.

Promise In Prgramming langulages

  • In E and AmbientTalk, a future is represented by a pair of values called a promise/resolver pair. 
  • In C++11 -  std::future 
  • In .NET - 4.0 System.Threading.Tasks.Task<T>, since .NET 4.5, through the async and await keywords
  • In Java - java.util.concurrent.Future

Promises in JavaScript

To make asynchronous patterns easier, JavaScript libraries have added an abstraction called promises.

First implementation

  • .then()
  • dojo.Deferred.resolve()
  • dojo.Deferred.reject()
  • dojo.xhrGet already return a dojo.Deferred
  • dojo.DeferredList

15.02.2008

The first widespread use of this pattern was with the dojo toolkit deferred object in version 0.9.

Common JS Promises API proposal

24.03.2009

First API Proposal

jQuery implementation

  • $.Deferred()
  • $.when().then()
  • dfd.resolve(), dfd.reject()

31.12.2011

jQuery introduced a new concept in version 1.5 called Deferred which is also a derivative implementation of the CommonJS Promises/A proposal.

What`s wrong whit $.Deferred

  • Different from dojo, jQuery does not return another promise from the then method. Instead, jQuery provides the pipe method to chain operations together.
  • Misses the sync - async parallel
  • Does not handle errors(throw)
  • Not interoperable with other 'thanable'
  • Only from 1.8 support returning a promise

Promises in jQuery

Promises in JavaScript

... so Domenic Denicola got angry and wrote

Promises in JavaScript

.then(appearedAfterFewMonth)

Success!

Promises now

  • >20 implementations of promises based on Promise/A+
  • version 1.1.1 of spec is ready
  • several other siblings spec are under development(promise creation, cancellation, progress)
  • DOMFuture promise library for using promises in DOM API
  • Convergence with Mark Miller concurrency strawman, for integrating promises into language [Done]
  • Part of ES6 Standard

Promises in Browsers

FF - 29+, Chrome 32+, Edge

function someAsyncFunction () {
    return new Promise(function (resolve, reject) {
        //all async staff goes her

        if(all is well) {
            resolve('Hurray');
        } else {
            reject('Something went wrong');
        }
    });
}

someAsyncFunction()
    .then(function (result) {
        console.log(result)     //Hurray
    }, function (error) {
        console.log(error)    //Something went wrong
    });

Promise in your code

  • Q, by Kris Kowal
  • When.js, by Brain Cavalier
  • RSVP.js, by Yehunda Katz
  • bluebird, by Petka Antonov
  • use transpilers for ES6 promises (Babel.js)

1. Chose a library (most popular are)

  • a replacement for events
  • a replacement for streams
  • a way of doing  functional reactive programming

2. If you see a jQuery promise - wrap it!

var realPromise = Q(jQueryPromise)

3. Keep sync/async paralel in mind

4. Promises are not:

Generators

Relatively new concept, that was introduced in ES6

Generators ideas

Wouldn't it be nice, that when you execute your function, you could pause it at any point, calculate something else, do other things, and then return to it, even with some value and continue?

Designed for iteration work

Solution of writing asynchronous code with generators is based on possibility to make a non-blocking  pause and wait (yield) until Promise will be resolved 

Generator Example

function * updateStoryComment(id) {
    try {
        var story = yield fetch('get/story/id');
        var comment = yield fetch('get/story/comment/id');
        var updatedText = yield asyncUserDialog();
        yield fetch('get/story/comment/id', method: 'POST', body: updatedText);
    } catch (ex) {
        handleErrorDuringUpdating()
    }
}

var generator = updateStoryComment(12);

generator.next().value.then(function (story) { // { value: resolvedPromise, done: false }  
    return generator.next(story).value;
}).then(function (comment) {
    return generator.next(comment).value;
}).then(function (updatedText) {
    return generator.next(updatedText).value;
}).then(function (){
    notifyUser();
});

While this is great for doing iteration work, it’s tedious from the perspective of doing asynchronous control flow

Using of CO and similar libraries can help but...

var co = require('co');

function updateStoryComment(id) {
    return co(function * updateStoryComment() {
        try {
            var story = yield fetch('get/story/id');
            var comment = yield fetch('get/story/comment/id');
            var updatedText = yield asyncUserDialog();
            yield fetch('get/story/comment/id', method: 'POST', body: updatedText);
        } catch (ex) {
            handleErrorDuringUpdating()
        }
    });
}

updateStoryComment(12).then(function() {
  notifyUser()
});

Generators in Browsers

FF - 29+, Chrome 39+

Async/Await

Introduced in ES7 - and currently only available using a transpiler. 

Async = co + generators - hacking

Under the hood async functions using Promises - this is why the async function will return with a Promise.

Async example

async function updateStoryComment(id) {
    try {
        var story = await fetch('get/story/id');
        var comment = await fetch('get/story/comment/id');
        var updatedText = await asyncUserDialog();
        await fetch('get/story/comment/id', method: 'POST', body: updatedText);
        notifyUser();
    } catch (ex) {
        handleErrorDuringUpdating()
    }
}

updateStoryComment(12);

You have to put the async keyword before the function declaration. After that, you can use the await keyword inside your newly created async function

Async / Await is amazing, the mecca of working with asynchronous code in JavaScript. Personally I think it’s a shame we got Generators in ES6 instead of this. The solution is so eloquent that it will forever change the way we write JavaScript.

They like working with Async code, what about you?

Thanks for listening!

Questions?

Want more?

Want more?

  • dsfsd
  • setTimeout in FireFox
Made with Slides.com