How in-sync are we with 'async' ?
Sidhartha Mitra
Tech Powered Growth Architect ?? | Founder, SidLabs LLP | Turning Digital Innovation into Tangible Results ??
...an article on using async functions with Es6 generators
#js #ES6 #webdevelopment
While being or aspiring to be a web developer and wile working with JS, have you come across declarations/expressions/method definitions/ arrow functions like the ones below ?
//function declaration async function foo() {} //function expression const foo = async function () {}; //method definition let obj = { async foo() {} } //arrow functions const foo = async () => {};
Well, if you have, then you must have come across this already! and you should (...imo) pursue learning them further!
Reason : While async functions can make your 'promises' more handy, they also help asynchronous programming get much easier. By just using an 'async' keyword before a function definition and an 'await' keyword inside that function, you no longer require to explicitly specify the dependencies of a function call on methods like .then(). Would you not agree that there will be scenarios where the results through callbacks are not available immediately, yes?
For example :
// Create an async function async function myAsyncFunction() { // Create a new promise const messagePromise = new Promise((resolve, reject) => { // Wait for 0.5s setTimeout(() => { // Resolve the promise resolve('critics are good for my work-health.') }, 500) }) // Invoke messagePromise and wait until it is resolved // Once it is resolved assign the resolved promise to a variable const messageResult = await messagePromise // NOTE: await will cause myAsyncFunction() to pause here // until the messagePromise is settled (resolved or rejected) // Log the result console.log(messageResult) } // Invoke the myAsyncFunction() function myAsyncFunction() // Output: // 'Promise is finished.'
Async with ES6 generators
I love generators because of its ability to provide a single-threaded and synchronous looking code style which helps a coder to smoke screen the a-synchronicity in her/his code. It also ensures a maintainable code which is easily readable and reusable for its synchronous looking 'appearance'.
Lets look at his very basic example :
We have this code already which we intend to improve,
function makeAjaxCall(url,cb) { // some ajax code out here // call the 'cb(result)' once done } makeAjaxCall("https:// your url.1", function(result1){ var data ?= JSON.parse(result1); makeAjaxCall("https:// your url.2/?id=", function(result2){ var resp = JSON.parse( result2 ); console.log( "The value you asked for: " + resp.value ); }); } );
Lets look at it the same code again using the request (..) helper function, which basically wraps the makeAjaxcall utility to make sure its callback invokes the generator iterator's next(..) method.
function request(url) { // this is where we're hiding the asynchronicity, // away from the main code of our generator // `it.next(..)` is the generator's iterator-resume // call makeAjaxCall( url, function(response){ it.next( response ); } ); // Note: nothing returned here! } function *main() { var result1 = yield request( "https://some.url.1" ); var data ?= JSON.parse( result1 ); var result2 = yield request( "https://some.url.2?id=" + data.id ); var resp = JSON.parse( result2 ); console.log( "The value you asked for: " + resp.value ); } var it = main(); it.next(); // get it all started
- So then we call yield .. (with that undefined value), which essentially does nothing but pause our generator at that point. It's going to wait until the it.next(..) call is made to resume, which we've queued up (as the callback) to happen after our Ajax call finishes.
- Also when it.next(..) is called as the Ajax callback, it's passing the Ajax response to it, which means that value is getting sent back into our generator at the point where it's currently paused, which is in the middle of the result1 = yield .. statement!
- Punch line : In essence, result1 = yield request(..) is asking for the value, but it's (almost!) completely hidden from us -- at least us not needing to worry about it here -- that the implementation under the covers causes this step to be asynchronous. It accomplishes that asynchronicity by hiding the pause capability in yield, and separating out the resume capability of the generator to another function, so that our main code is just making a synchronous(-looking) value request.
Hence, the power lies in abstracting away a-synchronicity as an implementation detail
Inspiration : davidwalsh
Tech Powered Growth Architect ?? | Founder, SidLabs LLP | Turning Digital Innovation into Tangible Results ??
4 å¹´Khaja Naquiuddin what do you think ?