Skip to main content

Command Palette

Search for a command to run...

Hey #SalesforceDevs! do you suffer from mild to moderate JavaScript? If so, Async/Await can help.

Updated
5 min read

Recently had a broseph tell me ‘Bro, Fr Fr do you even know how Async/Await works! Ya gotta use Promises.’

Honestly that bothered me more than a perky product owner up in my grill on a 8am standup after the dev team worked all weekend because said product owner can’t say no.

So I looked at myself in the mirror through a fork - turns out I don’t look good behind bars - and wrote this. So lets all sit around this dumpster fire and discuss JavaScript concurrency! This quest has three chapters.

🔄 Chapter 1: Callbacks (aka The Ancient Times when jQuery ruled the web and XMLHttpRequest was a novelty)

Back then, JavaScript was a relative babe, and as we all know from the Christmas songs, you have to wrap the babe in swaddling clothes - or in this case, callbacks. That led to developers writing callback hell. Yo check my comments here.

getAccount(accountId, function(account) { // getAccount()'s second argument is an anonymous function. AKA Callback. This anonymous method is executed by the JavaScript overlords when getAccount is finished.  
    getContacts(account.Id, function(contacts) { // Also uses Callbacks
        getOpportunities(contacts[0].Id, function(opps) { // If you guessed also a callback, you win.
            // Welcome to the pyramid of doom!
            // Population: Your sanitys
            // Work harder, no one cares.
        });
    });
});

We called this "callback hell" for a reason, folks. I once - and I can’t make this sh*t up - saw a function that had 33 nested callback methods. In a textbook. My therapist reminds me to go pet the dog at times like this. 🐕 If you’re wondering why this is terrible - well, I mean it works but that’s about the only bambi-kind thing I can say about it. This gets hard to break into maintainable-sized-methods and just … understanding the flow can be a challenge. Sure there were things you could do to de-structure this by calling named functions instead of anonymous ones, but … I don’t remember seeing a lot of that.

⚡ Chapter 2: Promises - The Betamax of JavaScript

So we hated on Callback hell an Promises came along and were like "Hold my coffee." ☕ Honestly most people were like ‘wtf is a promise’? Promises have a bit of a marketing problem. First, it’s a word that’s abused by politicians, managers everyone knows that PM. Secondly, it’s not sufficiently esoteric that you can Google it and get a very narrow set of explanations. Seriously, try Googling Promise; Yeah. Now try Googling ‘monad’. I’ll wait. See the difference? Personally, I think we should have called Promises ‘monadic composition’. Cause that’s … clearer. Check out this code while pondering my sanity.

getAccount(accountId)
    .then(account => getContacts(account.Id)) // look ma, no callback methods!
    .then(contacts => getOpportunities(contacts[0].Id)) // OMG None here either!
    .then(opps => {
        // Look Ma, no pyramid!
    })
    .catch(error => {
        // One error handler to rule them all
    });

Ok so the key takeaway for promises is this: A promise provides flow control (try/catch) for asynchronous work by allowing you to attach work - functions - to be executed after the previous step concludes. Promises use the then method to chain work together. Grammatically it makes sense right? do this, then that, then this other thing… Still not sure why they’re called ‘Promises’ but there’s a whole heap of JavaScript that falls in to the ‘WTFJS.com’ bucket. Honestly, JS as a language has all the hallmarks of a circular family tree, but … I don’t care what people say, I say it’s sweet.

Regardless of naming issues, Promises make our lives easier if for no other reason than there’s much less code to reason about. They’re also … just conceptually simpler. Once you grasp the language guarantee that each then() function is blocked from executing until the previous one completes… you’re good to go.

This is, as they say in my hood, ‘much better’. But let’s be honest, it feels a bit like someone shoehorned that into the language. (oh wait…) I mean, wouldn’t it be nice if the concurrency framework was keywords or operators instead of methods?

🌟 Chapter 3: Async/Await - The T.S. Evermore Era of JavaScript concurrency (Her best era. There, I said it.)

Async and Await are keywords. Inside any method that you’ve prefaced with async you can use the await keyword

Here's the plot twist Broseph: Async/Await isn't new bbq sauce - it's just lipstick on the promise of a pig. AKA Promises wearing a really flattering Chelsea jersey. Check my comments yo.

async function getAccountData() { // <- we start with that async keyword. 
    try { // but wait, what's this? more on that later larry.
        const account = await getAccount(accountId); // see that await? that stops execution of the following lines until it's completed. 
        const contacts = await getContacts(account.Id); // Yep, another pause.
        const opps = await getOpportunities(contacts[0].Id); // one more pause for good measure.
        // Same Promise chain, but reads like synchronous code! 
    } catch(error) {
        // Still just a .catch() under the hood which is how we can use a try/catch with async code
    }
}

So here we got some asynchronous code that reads like synchronous code. And that’s pretty badass. Here’s your key takeaway for Async/Await - It allows developers to write Async code that reads Synchronously. Keep in mind that every await keyword means the rest of the method is paused until the await’d line has completed (or errored out).

I, for one, think this is the only way one should write Async JavaScript. And honestly, you’ve read this far, so you must think this dog can hunt. But in my head (and inbox) I’m hearing people complain that Async/Await and Promises do different things so… Ok Broseph… here’s how Async/Await works under the covers: Every async function actually returns a Promise. This is literally(Yeah, read that with an exasperated valley accent) the same as our Promise example above:

// These are functionally identical!
async function getData() {
    return await fetchSomething();
}

function getData() {
    return Promise.resolve(fetchSomething());
}

🖖 So what does this mean for you?

If’n your a Salesforce dev writing some mighty fine LWC’s - you should use Async/Await. Anything else makes Codey Cry. Seriously, like you rubbed his eyes with onions. Just Bawling. Don’t do it, he’s not done nothing to deserve it. Even the creepy animatronic version.

Today You learned? You can Await your imperatively executed wire methods. const foo = await myPreciousApexMethod()

Next time someone tells you Promises are better/faster/stronger/different than Async/Await, ask them if they’re interested in signing a petition to ban dihydrogen-monoxide…

Thank you for coming to my ted talk, and remember only you can prevent stupid code.