JavaScript the Fun Part


modern-javascript

async-await


In the previous post we saw that by a wrapper function we can somehow synchronize our promise function with out main thread (= main task).

This was the example:

const log = console.log.bind( console );
log( "--- start ---" );

function toUpperCaseLater( string ){
    return new Promise(function( resolve ){
        setTimeout(function(){
            resolve( string.toUpperCase() );
        }, 3000);
    });
}
/*
function asycn2UpperCase( input ){
    const lowerCase = input;
    log( "lowerCase:", lowerCase );
    const  upperCase = toUpperCaseLater( lowerCase ).then( r => { log( r )} );
    log( "upperCase:", upperCase );
}
*/
function asycn2UpperCase( input ){
    const lowerCase = input;
    log( "lowerCase:", lowerCase );
    
    // wrap our code in a wrapper function
    function sync( data ){
        const upperCase = data;
        log( "upperCase:", upperCase );
    }

    // pass wrapper function to then()
    toUpperCaseLater( lowerCase ).then( r => sync( r ) );

    // no code after toUpperCaseLater() function
}
asycn2UpperCase( "how are you today?" )
console.log( "---- end ----" );

and the output is

--- start ---
lowerCase: how are you today?
---- end ----
upperCase: HOW ARE YOU TODAY?

Good looking syntax

By looking the code it is not quite obvious what it does and therefore in ES2017 async-await was introduced to tackle this issue.

Here is the same code and the same output by using async-await wrapper.

const log = console.log.bind( console );
log( "--- start ---" );

function toUpperCaseLater( string, sync ){
    return new Promise(function( resolve ){
        setTimeout(function(){
            resolve( string.toUpperCase() );
        }, 1000);
    });
}

async function asycn2UpperCase( input ){
    // these two line is part of main task
    // main thread
    const lowerCase = input;
    log( "lowerCase:", lowerCase );

    // these two line is part of helper thread
    // micro task
    const upperCase = await toUpperCaseLater( lowerCase );
    log( "upperCase:", upperCase );
}

asycn2UpperCase( "how are you today?" )
console.log( "---- end ----" );

and the output:

--- start ---
lowerCase: how are you today?
---- end ----
upperCase: HOW ARE YOU TODAY?

Is not it much cleaner? Yes it is and developers feel that really there is a await operation which there is not.

The async function declaration defines an asynchronous function, which returns an AsyncFunction object. An asynchronous function is a function which operates asynchronously via the event loop, using an implicit Promise to return its result. But the syntax and structure of your code using async functions is much more like using standard synchronous functions.

Multi async-await

Surprisingly, we can easily use many async-await without too much confusing.

Here is an example for converting an array of string to uppercase.

const log = console.log.bind( console );
log( "--- start ---" );

function toUpperCaseLater( string, sync ){
    return new Promise(function( resolve ){
        setTimeout(function(){
            resolve( string.toUpperCase() );
        }, 1000);
    });
}

async function asycn2UpperCase( list ){
    log( `convert all ${list} to uppercase` );
    const how = await toUpperCaseLater( list.shift() );
    log( "list[0]:", how );
    
    const are = await toUpperCaseLater( list.shift() );
    log( "list[1]:", are );
    
    const you = await toUpperCaseLater( list.shift() );
    log( "list[2]:", you );
    
    const today = await toUpperCaseLater( list.shift() );
    log( "list[3]:", today );
}

asycn2UpperCase( [ "how", "are", "you", "today?" ] )
console.log( "---- end ----" );

and the output

--- start ---
convert  all how,are,you,today? to uppercase
---- end ----
list[0]: HOW
list[1]: ARE
list[2]: YOU
list[3]: TODAY?

Really async-await

If we run the code above (= multi-async-await) using time Linux utility we will have:

time node  async-await-2.js 
--- start ---
convert all how,are,you,today? to uppercase
---- end ----
list[0]: HOW
list[1]: ARE
list[2]: YOU
list[3]: TODAY?

real	0m4.150s
user	0m0.129s
sys	0m0.022s

Hmmm! about 4 seconds! Do we really have asynchronous code? Or just we have synchronized them? Which one?

It seems that for four await; we have waited 1 second for each one; so we have four ones, and we have waited totally +4 seconds.

In other words it seems that we run one after another or one by one and not all four await at the same time!

Lets investigate this more in next post.


Update: Tue Oct 01 2019 07:50:30 GMT+0330 (Iran Standard Time)