Assembly in Progress...

Asynchronous Code with JS

Promises

A promise returns the same data as a callback function, but it can await the reply. With this, when there is a delay in receiving data, the syntax is nicer, and it provides better error handling. Most importantly, the browser can continue processing the page and then fill in the delayed data whenever it is ready.

This allows JavaScript to step away from the normal synchronous processing order—running commands one after the other in the order they are written—and begin processing some of the code asynchronously. This will allow the browser to move on while the asynchronous code is temporarily set aside. For more details on how JavaScript is processed, read this →.

While setting up a promise enables the browser to continue its work, it is the value that the promise returns that makes it useful. This return will occur whether the operation was successful or not.

resolve(param) is a function called when the promised function is done with its work and has successfully completed its task.

reject(param) is a function called when the promised function encounters an error and is unable to complete.

Returning a promise signals that the function will finish when its work is done.

A nice article by Dominic Denicola breaks down the responses in a great way. Ultimately, here is what is possible to receive back from a promise:

  • states: fulfilled, rejected, pending.
  • fates: resolved, unresolved.

.then(function to handle response, function to handle error) can be used when the function is invoked to chain actions together. Once a response is received indicating the program can move on, the next step in the then chain will be implemented.

let myVar = new Promise( (resolve, reject) => { ...logic})

NOTE: the names for resolve and reject can be any names, but these two names are general convention. These return functions accordingly.

↓ Examples ↓

function myAsynchFun() {
    let promise = new Promise((resolve, reject) => {

        //    Set up error variable
        let error = false;

        setTimeout(() => {
            console.log('Working Asynchronously')

            if (error) {

                reject('Error');

            } else {

                resolve('Work Done');
            }

        }, 1000)
    })

    return promise
}

Promise All

Promise.all() will resolve a series of promises and return an array of their results.

↓ Example ↓

const promise1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'Hello!');
})

const promise2 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 'There are many...');
})

const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 2000, 'Promises running...');
})

const promise4 = new Promise((resolve, reject) => {
    setTimeout(resolve, 3000, 'and returning together!');
})

Promise.all([promise1, promise2, promise3, promise4]).then(values => {
    console.log(values)
});

//    RESULT: Promise {< pending >}
//    ...after 3 seconds...
//    RESULT: (4) ["Hello!", "There are many...", "Promises running...", "and returning together!"]
// 0: "Hello!"
// 1: "There are many..."
// 2: "Promises running..."
// 3: "and returning together!"
// length: 4
// __proto__: Array(0)



////////////////////////
Full Real - World Example
////////////////////////

const urls = [
    'https://jsonplaceholder.typicode.com/users',
    'https://jsonplaceholder.typicode.com/posts',
    'https://jsonplaceholder.typicode.com/albums'
]

Promise.all(urls.map(url => {

    return fetch(url).then(resp => resp.json())

})).then(results => {

    console.log(results[0]);
    console.log(results[1]);
    console.log(results[2]);

}).catch(

 () => console.log('error')
);

Async-Await Functions

Async functions return a promise. These make code concerning promises easier to read.

async function functName() { ...code await ...code}

↓ Examples ↓

//    See the Promises section to see the break-down of the myAsynchFun() function
myAsynchFun().then(

        (success) = & gt; console.log(success)
    )
    .catch(

        ((error) = & gt; console.log(error)

        ); // .catch() can be used to catch the error

        //    RESULT: "Working Asynchronously"
        //"Work Done"



////////////////
Another example
////////////////

//    Without Async-Await
movePlayer(100, 'left')
 .then(() = & gt; movePlayer(400, 'right'))
 .then(() = & gt; movePlayer(10, 'right'))
    .then(() = & gt; movePlayer(330, 'left'))

    //    With Async-Await
    async function playerStart() {
     const firstMove = await movePlayer(100, 'left'); //pause
     const secondMove = await movePlayer(100, 'left'); //pause
     const thirdMove = await movePlayer(10, 'right'); //pause
     const fourthMove = await movePlayer(330, 'left'); //pause
    }



////////////////
Another example
////////////////

//    Without Async-Await
fetch('https://jsonplaceholder.typicode.com/users')
 .then(resp = & gt; resp.json())
 .then(console.log)

//    With Async-Await
async function fetchUsers() {
 const resp = await fetch('https://jsonplaceholder.typicode.com/users');
 const data = await resp.json();
 console.log(data);
}

fetchUsers();

For-Await-Of Loop

For-await-of loops through promises and returns responses in the correct order.

async function functName() { for await (let request of arrayOfPromises) }

↓ Examples ↓

//    Set an array
const theUrls = [
    'https://jsonplaceholder.typicode.com/users',
    'https://jsonplaceholder.typicode.com/posts',
    'https://jsonplaceholder.typicode.com/albums'
]

//    A standard for-of loop for refernce
const loopThroughUrls = theUrls => {
    for (url of theUrls) {
        console.log(url);
    }
}

//    Now, a for-of-await loop
const getData = async function() {
    const arrayOfPromises = theUrls.map(url => fetch(url));
    for await (let request of arrayOfPromises) {
        const data = await request.json();
        console.log(data)
    }
}

getData();

//    RESULT:Promise {< pending >}
//(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
//(100) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
//(100) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]

Managing Asynchronous Ordering

There are times when the order in which code runs, even in an asynchronous environment. There are three common methods: parallel, sequential and race

//    This function uses timed delay to order the promises.
const promisify = (item, delay) =>
    new Promise((resolve) =>
        setTimeout(() =>
            resolve(item), delay));

const a = () => promisify('a', 100);
const b = () => promisify('b', 5000);
const c = () => promisify('c', 3000);

//    This runs them in parallel, then returns after all have finished.
async function parallel() {
    const promises = [a(), b(), c()];
    const [output1, output2, output3] = await Promise.all(promises);
    return `parallel is done: ${output1} ${output2} ${output3}`
}

//    This returns after the first promise is ready
async function race() {
    const promises = [a(), b(), c()];
    const output1 = await Promise.race(promises);
    return `race is done: ${output1}`;
}

//    This runs the Promises in a sequence and then returns
async function sequence() {
    const output1 = await a();
    const output2 = await b();
    const output3 = await c();
    return `sequence is done ${output1} ${output2} ${output3}`
}

sequence().then(console.log)
parallel().then(console.log)
race().then(console.log)

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

q
↑ Back to Top