Async in JS!

How to express and manipulate program behavior spread out over a period of time?

 

not about what happens from the beginning of a for loop to the end of a for loop

It's about what happens when part of your program runs now, and another part of your program runs later

  • waiting for user input
  • requesting data from a database or file system
  • sending data across the network and waiting for a response
  • etc, etc.

your program is almost certainly comprised of several chunks, only one of which is going to execute now, and the rest of which will execute later

// ajax(..) is some arbitrary Ajax function given by a library
var data = ajax( "http://some.url.1" );

console.log( data );
// what's the output?
The simplest way of "waiting" from now until later is to use a function, commonly called a callback function:
// ajax(..) is some arbitrary Ajax function given by a library
ajax( "http://some.url.1", function myCallbackFunction(data){

    console.log( data ); // Yay, I gots me some `data`!

} );
// which code runs now and which later? :P

function now() {
    return 21;
}

function later() {
    answer = answer * 2;
    console.log( "Meaning of life:", answer );
}

var answer = now();

setTimeout( later, 1000 ); // Meaning of life: 42

Gyaan

Any time you wrap a portion of code into a function and specify that it should be executed in response to some event (timer, mouse click, Ajax response, etc.), you are creating a later chunk of your code, and thus introducing asynchrony to your program.

JS is not asynchronous

Yes, JS is an on-demand execution engine and works when asked to!

Hosting Environments

  • Browsers
  • NodeJS servers
  • etc, etc

Explain Ajax Request 

// `eventLoop` is an array that acts as a queue (first-in, first-out)
var eventLoop = [ ];
var event;

// keep going "forever"
while (true) {
    // perform a "tick"
    if (eventLoop.length > 0) {
        // get the next event in the queue
        event = eventLoop.shift();

        // now, execute the next event
        try {
            event();
        }
        catch (err) {
            reportError(err);
        }
    }
}

Quiz Master Mathan

Callback Challenge # 1

listen( "click", function handler(evt){
    setTimeout( function request(){
        ajax( "http://some.url.1", function response(text){
            if (text == "hello") {
                handler();
            }
            else if (text == "world") {
                request();
            }
        } );
    }, 500) ;
} );

Callback Challenge # 2

doA( function(){
    doB();

    doC( function(){
        doD();
    } )

    doE();
} );

doF();


// doA()
// doF()
// doB()
// doC()
// doE()
// doD()

Trust Issues :P

// A
ajax( "..", function(..){
    // C
    // now you've just handed over your piece of code
    // to a third party!
    // are you absolutely sure this third-party
    // lib ajax will call your callback?
} );
// B

Trust Issues :P Contd.

// exaggerated scenario

analytics.trackPurchase( purchaseData, function(){
    chargeCreditCard();
    displayThankyouPage();
} );

Trust Issues :P Contd.

// exaggerated scenario

var tracked = false;

analytics.trackPurchase( purchaseData, function(){
    if (!tracked) {
        tracked = true;
        chargeCreditCard();
        displayThankyouPage();
    }
} );

Problems that can occur

  • Call the callback too early (before it's been tracked)
  • Call the callback too late (or never)
  • Call the callback too few or too many times (like the problem you encountered!)
  • Fail to pass along any necessary environment/parameters to your callback
  • Swallow any errors/exceptions that may happen
  • ...

And you thought the only problem with callbacks was sideways nesting, Ha!

Async in JS!

By Ankeet Maini

Async in JS!

  • 168