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');
    });
}