JSFiddle - React, Tailwind, and code Playground
by cdaringe
HTML
<script src="//cdn.jsdelivr.net/es6-promise/0.1.1/promise.js"></script>
<h1>Injecting async Promises into functions with serial/syncronous flow</h1>
<h4>You may commonly desire a function to have syncronous overall flow, however, you want to exploit some async goodness mixed in in the middle, then to converge again</h4>
<p>A strategy I like it to have your async calls:</p>
<ol>
<li>Return a promise to an array along with the other async promises you're making (perhaps the async call on many data items)</li>
<li>build up the data that you need asyncronously</li>
<li>Include the rest of your syncronous code as a subroutine of Promise.all(YOUR_ARRAY_OF_ASYNC_PROMISES)</li>
</ol>
<p>Now your async calls have finished, you have a data object to play with, and can continue sync execution. Toggle the two functions @the top of the js pane to see the difference.</p>
<div class="log">
<h3>Log</h3>
<ul id="log"></ul>
</div>
CSS
.log {
background-color:#FFEAB6;
border-radius:5px;
font-family:"Helvetica", Arial;
padding: 10px;
}
JavaScript
IntendedToBeSync(); //watch us run a function with async calls in the middle
//IsSync(); //is sync, with some async guts
function post(txt) {
var newItem = document.createElement("li");
newItem.innerHTML += txt;
document.getElementById('log').appendChild(newItem);
}
function aSyncFubarIt(results) {
var response = '';
if (!results) response = 'Did you expect me to finish inside the forEach!? It\'s unlikely that I will!';
else response = 'I\'m an async call! I likely won\'t finish in the map(), but I\'ll finish before .all executes!';
return new Promise(function (resolve, reject) {
window.setTimeout(function () {
if (results) results.push(response);
resolve(response);
}, 50);
});
}
function IntendedToBeSync() {
var data = [1, 2, 3];
post('start IntendedToBeSync - la la la, synchronous code...');
post(' IntendedToBeSync - start sub-asyncs');
data.forEach(function (item, ndx, arry) {
post('_mid forEach : ' + item);
aSyncFubarIt().then(post); //am I doing something async, but stopping execution to the next sync steps outside of this forEach? no. it's still async
});
post(' IntendedToBeSync - end contained asyncs');
post('end IntendedToBeSync');
}
function IsSync() {
var data = [4, 5, 6],
asyncResults = [];
post('start IsSync - la la la, synchronous code...');
post('IntendedToBeSync - start promise');
var pdata = data.map(function (item, ndx, arry) {
post('_mapping - do sync & async things : ' + item);
return aSyncFubarIt(asyncResults); //still async
});
//all async is done now - proceed on with the chlorophyll
Promise.all(pdata).then(function () {
asyncResults.forEach(function (result) {
post(result);
});
post('IntendedToBeSync - end asyncs');
});
}