Javascript async and await Primer Tutorial

Javascript async and await Primer Tutorial

Javascript async and await Primer Tutorial

Related Javascript asynchronous functionality to that of Promise All Object Tutorial‘s Promise object is async and await Javascript keywords.

As you can see in our David Walsh inspired Javascript function introduced into the Promise object code of recent times …


// Would take only 5000ms total!
async function parallel() {
const wait1 = get('//www.rjmprogramming.com.au/HTMLCSS/sleep.php?n=5');
const wait2 = get('//www.rjmprogramming.com.au/HTMLCSS/sleep.php?n=4');
await wait1;
await wait2;
return "done!";
}

… the async keyword changes the modus operandi of the Javascript function it modifies, giving that Javascript function asynchronous capabilities, and the await keyword kicks off (those) asynchronous “definitions of tasks to do”.

In addition, we have introduced a second timer via setTimeout so that the user can see what we do in context, and what we do today with this async and await “framework” is to play the same video twice, the second playing delayed by, as you may have guessed by now, 4 seconds. Why 4 seconds? As with all event-driven programming enthusiasts, you look for “intervention” (of code, via event) opportunities, and as you can see from the async and await “framework” code above, there is bound to be an intervention point as the PHP sleep.php invocation of lesser duration (rather than first!), ends.

In working this “duelling videos” in synchronicity idea, we discovered (via this useful link, thanks) a cute #t=[seconds] syntax we hadn’t used to start a homegrown video and/or audio at a specified time position, and shown at the “event intervention” place of code …


function get(url) {
// Return a new promise.
return new Promise(function(resolve, reject) {
// Do the usual XHR stuff
var req = new XMLHttpRequest();
req.open('GET', url);

req.onreadystatechange = function () {
//document.title='' + req.readyState + ' ' + req.status;
if (req.readyState == 4 && req.status == 200) {
console.log(req.responseText);
if (cell.indexOf("centre") == -1) {
document.getElementById(cell).innerHTML=req.response;
if (req.response.indexOf('ighthous') != -1 || damdone) {
adate=new Date();
document.getElementById('middle').innerHTML+=adate.toLocaleString() + '<br>' + 'australian_lighthouses.php Ajax response<br><br>';
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + 'australian_lighthouses.php Ajax response<br><br>';
adate=new Date();
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + 'australian_lighthouses.php IFRAME src<br><br>';
if (1 == 1) {
document.getElementById('h' + cell).innerHTML+='<iframe id="i' + cell + '" onload="ldone(' + "'australian_lighthouses.php'" + ');" style="display:none;width:800px;float:left;height:900px;" src="//www.rjmprogramming.com.au/PHP/australian_lighthouses.php#selsort" title="Lighthouses in Australia"></iframe>';
} else {
document.getElementById('h' + cell).innerHTML+='<iframe onload="ldone(' + "'australian_lighthouses.php'" + ');" style="width:800px;float:left;height:900px;" src="//www.rjmprogramming.com.au/PHP/australian_lighthouses.php#selsort" title="Lighthouses in Australia"></iframe>';
}

} else {
adate=new Date();
document.getElementById('middle').innerHTML+=adate.toLocaleString() + '<br>' + 'dams_usa.htm Ajax response<br><br>';
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + 'dams_usa.htm Ajax response<br><br>';
damdone=true;

wis='' + eval(eval(window.getComputedStyle(document.getElementById(cell), null).getPropertyValue("width").replace('px','')) - 0) + 'px';
adate=new Date();
if (document.getElementById('hmiddle').innerHTML == "") document.getElementById('hmiddle').innerHTML=document.getElementById('middle').innerHTML;
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + 'dams_usa.htm IFRAME src<br><br>';
if (1 == 1) {
document.getElementById('h' + cell).innerHTML+='<iframe id="i' + cell + '" onload="ldone(' + "'dams_usa.htm'" + ');" style="display:none;width:' + wis + ';float:left;height:900px;" src="//www.rjmprogramming.com.au/HTMLCSS/dams_usa.htm" title="Dams in the USA"></iframe>';
} else {
document.getElementById('h' + cell).innerHTML+='<iframe onload="ldone(' + "'dams_usa.htm'" + ');" style="width:' + wis + ';float:left;height:900px;" src="//www.rjmprogramming.com.au/HTMLCSS/dams_usa.htm" title="Dams in the USA"></iframe>';
}
}
if (cell == "right") {
cell="centre";
} else {
cell="right";
}
} else {
adate=new Date();
if (cell == 'centre') {
document.getElementById('middle').innerHTML+=adate.toLocaleString() + '<br>' + 'sleep.php?n=75 Ajax response<br><br>';
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + 'sleep.php?n=75 Ajax response<br><br>';
document.getElementById('ileft').style.display='block';
document.getElementById('iright').style.display='block';
} else {
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + 'sleep.php?n=' + cell.replace('centre','') + ' Ajax response<br><br>';
if (cell.indexOf('4') != -1) {
document.getElementById('hleft').innerHTML='<video controls="controls" onended="atend(this);" autoplay="autoplay" id="vleft"><source id="vsource" src="//www.rjmprogramming.com.au/Mac/ImageFit_Paintbrush.m4v#t=4" type="video/mp4"></source></video>';
document.getElementById('hright').innerHTML='<video controls="controls" onloadstart="atstart(this);" onended="atend(this);" autoplay="autoplay" id="vright"><source src="//www.rjmprogramming.com.au/Mac/ImageFit_Paintbrush.m4v#t=4" type="video/mp4"></source></video>';
}

cell=cell.replace('centre4','centre05').replace('centre5','centre04').replace('centre0','centre');
}
}
}
};

// Handle network errors
req.onerror = function() {
reject(Error("Network Error"));
};

// Make the request
req.send();
});

To wind up the “information flow” we gave the videos onended event places, thanks to this webpage’s advice, thanks, to say when the videos finish, with its imperfect synchronicity, but “often will be to the same second” timer time.

Here is the amended HTML and Javascript you could call promises_test.htm and here is what changed for async and await usage. The relevant live run link is here, or is that there.

Stop Press

We found we could improve “imperfect synchronicity” by effectively resetting the “earlier started” video at the same time the delayed video starts.


Previous relevant Promise All Object Tutorial is shown below.

Promise All Object Tutorial

Promise All Object Tutorial

Building on yesterday’s Promise Object Primer Tutorial start to the Promise object asynchronous processing research we are up to, we move on to try David Walsh‘s Promise.all syntax …


Promise.all([promise1, promise2]).then(function(results) { // method takes an array of promises and fires one callback once they are all resolved
// Both promises resolved
})
.catch(function(error) {
// One or more promises was rejected
});

… and can’t say that the new live run followed into “bowels” of the flow of the syntax, but worked with what was tried, elsewhere, and kicked off with Promise.all and before we forget, none of this works in Internet Explorer. And what was that “try” all about? “Catch” this. We load the 2 web applications last night asynchronously in Ajax (invisibly) and then onto IFRAME src= loading (also invisible), but add into the mix a PHP Ajax call (all encased within the Promise.all method syntax) that sleeps for 75 seconds. The idea here is that it is only after all three web applications finish their Ajax we display those IFRAME elements made invisible earlier. The user sees the Dams in the USA, now, only well into its long read of data with the progress bar showing a good amount of progress. Note here, we don’t pretend just client solutions can really sleep, as PHP represents a server side solution to this sleep issue we started talking about yesterday.

Here is the amended HTML and Javascript you could call promises_test.htm and here is what changed. Here is the very simple PHP sleep.php


<?php if (isset($_GET['n'])) { sleep($_GET['n']); echo "<p>Slept for " . $_GET['n'] . " seconds.</p>"; } else { sleep(20); echo "<p>Slept for 20 seconds.</p>"; } ?>

You can also see this play out at WordPress 4.1.1’s Promise All Object Tutorial.


Previous relevant Promise Object Primer Tutorial is shown below.

Promise Object Primer Tutorial

Promise Object Primer Tutorial

The Promise Javascript object opens up methods where you, as a web application client side programmer, can end up with a single variable approach to the management of asynchronous processes …

… but the use of this can’t hide the issue of what to do with client side logic to do nothing, what we think of as “sleep” in those “reject” parts of the diagram above.

We’ve started our journey of understanding, with inspiration from this useful link (and this one), thanks, of Promise Javascript object by doing the document.body onload event loaded


<script type='text/javascript'>
var lleft=false, lright=false, cell="left", damdone=false;
var wis, adate;


// From Jake Archibald's Promises and Back:
// //www.html5rocks.com/en/tutorials/es6/promises/#toc-promisifying-xmlhttprequest

function get(url) {
// Return a new promise.
return new Promise(function(resolve, reject) {
// Do the usual XHR stuff
var req = new XMLHttpRequest();
req.open('GET', url);

req.onreadystatechange = function () {
//document.title='' + req.readyState + ' ' + req.status;
if (req.readyState == 4 && req.status == 200) {
console.log(req.responseText);
document.getElementById(cell).innerHTML=req.response;
if (req.response.indexOf('ighthous') != -1 || damdone) {
adate=new Date();
document.getElementById('middle').innerHTML+=adate.toLocaleString() + '<br>' + 'australian_lighthouses.php Ajax response<br><br>';
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + 'australian_lighthouses.php Ajax response<br><br>';
adate=new Date();
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + 'australian_lighthouses.php IFRAME src<br><br>';
document.getElementById('h' + cell).innerHTML+='<iframe onload="ldone(' + "'australian_lighthouses.php'" + ');" style="width:800px;float:left;height:900px;" src="//www.rjmprogramming.com.au/PHP/australian_lighthouses.php#selsort" title="Lighthouses in Australia"></iframe>';
} else {
adate=new Date();
document.getElementById('middle').innerHTML+=adate.toLocaleString() + '<br>' + 'dams_usa.html Ajax response<br><br>';
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + 'dams_usa.html Ajax response<br><br>';
damdone=true;
wis='' + eval(eval(window.getComputedStyle(document.getElementById(cell), null).getPropertyValue("width").replace('px','')) - 0) + 'px';
adate=new Date();
if (document.getElementById('hmiddle').innerHTML == "") document.getElementById('hmiddle').innerHTML=document.getElementById('middle').innerHTML;
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + 'dams_usa.html IFRAME src<br><br>';
document.getElementById('h' + cell).innerHTML+='<iframe onload="ldone(' + "'dams_usa.html'" + ');" style="width:' + wis + ';float:left;height:900px;" src="//www.rjmprogramming.com.au/HTMLCSS/dams_usa.html" title="Dams in the USA"></iframe>';
}
cell="right";
}
};

// Handle network errors
req.onerror = function() {
reject(Error("Network Error"));
};

// Make the request
req.send();
});
}

function ldone(what) {
adate=new Date();
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + what + ' IFRAME loaded<br><br>';
}

function ol() {
adate=new Date();
document.getElementById('middle').innerHTML+=adate.toLocaleString() + '<br>' + 'australian_lighthouses.php get()<br><br>';
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + 'australian_lighthouses.php get()<br><br>';
get('//www.rjmprogramming.com.au/PHP/australian_lighthouses.php').then(function(response) {
console.log("Success!", response);
}, function(error) {
console.error("Failed!", error);
});

adate=new Date();
document.getElementById('middle').innerHTML+=adate.toLocaleString() + '<br>' + 'dams_usa.html get()<br><br>';
document.getElementById('hmiddle').innerHTML+=adate.toLocaleString() + '<br>' + 'dams_usa.html get()<br><br>';
get('//www.rjmprogramming.com.au/HTMLCSS/dams_usa.html').then(function(response) {
console.log("Success!", response);
}, function(error) {
console.error("Failed!", error);
});

}

</script>

… asynchronous Ajax XMLHttpRequest() calls and follow this up with IFRAME src= calls, the difference being, the latter method loads any Javsacript and CSS styling in the <head></head> tag whereas the former doesn’t. We like the neatness of the syntax here, but still need those “reject” places to be able to effectively sleep to not overload your web browser with activity … and that’s where we’ll leave you with a live run HTML and Javascript promises_test.html source code link, thinking on that.

If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.


If this was interesting you may be interested in this too.

This entry was posted in Ajax, eLearning, Event-Driven Programming, Tutorials and tagged , , , , , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>