Tag: Async

Understanding Async Await

When writing code for the web, eventually you’ll need to do some process that might take a few moments to complete. JavaScript can’t really multitask, so we’ll need a way to handle those long-running processes.

Async/Await is a way to handle this type of time-based sequencing. It’s especially great for when you need to make some sort of network request and then work with the resulting data. Let’s dig in!

Promise? Promise.

Async/Await is a type of Promise. Promises in JavaScript are objects that can have multiple states (kind of like the real-life ones ☺️). Promises do this because sometimes what we ask for isn’t available immediately, and we’ll need to be able to detect what state it is in.

Consider someone asks you to promise to do something for them, like help them move. There is the initial state, where they have asked. But you haven’t fulfilled your promise to them until you show up and help them move. If you cancel your plans, you rejected the promise.

Similarly, the three possible states for a promise in JavaScript are:

  • pending: when you first call a promise and it’s unknown what it will return.
  • fulfilled: meaning that the operation completed successfully
  • rejected: the operation failed

Here’s an example of a promise in these states:

Here is the fulfilled state. We store a promise called getSomeTacos, passing in the resolve and reject parameters. We tell the promise it is resolved, and that allows us to then console log two more times.

const getSomeTacos = new Promise((resolve, reject) => {   console.log("Initial state: Excuse me can I have some tacos");    resolve(); })   .then(() => {     console.log("Order some tacos");   })   .then(() => {     console.log("Here are your tacos");   })   .catch(err => {     console.error("Nope! No tacos for you.");   });
> Initial state: Excuse me can I have some tacos > Order some tacos > Here are your tacos

See the Pen
Promise States
by Sarah Drasner (@sdras)
on CodePen.

If we choose the rejected state, we’ll do the same function but reject it this time. Now what will be printed to the console is the Initial State and the catch error:

const getSomeTacos = new Promise((resolve, reject) => {   console.log("Initial state: Excuse me can I have some tacos");    reject(); })   .then(() => {     console.log("Order some tacos");   })   .then(() => {     console.log("Here are your tacos");   })   .catch(err => {     console.error("Nope! No tacos for you.");   });
> Initial state: Excuse me can I have some tacos > Nope! No tacos for you.

And when we select the pending state, we’ll simply console.log what we stored, getSomeTacos. This will print out a pending state because that’s the state the promise is in when we logged it!

console.log(getSomeTacos)
> Initial state: Excuse me can I have some &#x1f32e;s > Promise {<pending>} > Order some &#x1f32e;s > Here are your &#x1f32e;s

What then?

But here’s a part that was confusing to me at first. To get a value out of a promise, you have to use .then() or something that returns the resolution of your promise. This makes sense if you think about it, because you need to capture what it will eventually be — rather than what it initially is — because it will be in that pending state initially. That’s why we saw it print out Promise {<pending>} when we logged the promise above. Nothing had resolved yet at that point in the execution.

Async/Await is really syntactic sugar on top of those promises you just saw. Here’s a small example of how I might use it along with a promise to schedule multiple executions.

async function tacos() {   return await Promise.resolve("Now and then I get to eat delicious tacos!") };  tacos().then(console.log)

Or a more in-depth example:

// this is the function we want to schedule. it's a promise. const addOne = (x) => {   return new Promise(resolve => {     setTimeout(() => {        console.log(`I added one! Now it's $  {x + 1}.`)       resolve()     }, 2000);   }) }  // we will immediately log the first one,  // then the addOne promise will run, taking 2 seconds // then the final console.log will fire async function addAsync() {   console.log('I have 10')   await addOne(10)   console.log(`Now I'm done!`) }  addAsync()
> I have 10 > I added one! Now it's 11. > Now I'm done!

See the Pen
Async Example 1
by Sarah Drasner (@sdras)
on CodePen.

One thing (a)waits for another

One common use of Async/Await is to use it to chain multiple asynchronous calls. Here, we’ll fetch some JSON that we’ll use to pass into our next fetch call to figure out what type of thing we want to fetch from the second API. In our case, we want to access some programming jokes, but we first need to find out from a different API what type of quote we want.

The first JSON file looks like this- we want the type of quote to be random:

{   "type": "random" }

The second API will return something that looks like this, given that random query parameter we just got:

{   "_id":"5a933f6f8e7b510004cba4c2",   "en":"For all its power, the computer is a harsh taskmaster. Its programs must be correct, and what we wish to say must be said accurately in every detail.",   "author":"Alan Perlis",   "id":"5a933f6f8e7b510004cba4c2" }

We call the async function then let it wait to go retrieve the first .json file before it fetches data from the API. Once that happens, we can do something with that response, like add it to our page.

async function getQuote() {   // get the type of quote from one fetch call, everything else waits for this to finish   let quoteTypeResponse = await fetch(`https://s3-us-west-2.amazonaws.com/s.cdpn.io/28963/quotes.json`)   let quoteType = await quoteTypeResponse.json()      // use what we got from the first call in the second call to an API, everything else waits for this to finish   let quoteResponse = await fetch("https://programming-quotes-api.herokuapp.com/quotes/" + quoteType.type)   let quote = await quoteResponse.json()    // finish up   console.log('done') }

We can even simplify this using template literals and arrow functions:

async function getQuote() {   // get the type of quote from one fetch call, everything else waits for this to finish   let quoteType = await fetch(`quotes.json`).then(res => res.json())      // use what we got from the first call in the second call to an API, everything else waits for this to finish   let quote = await fetch(`programming-quotes.com/$  {quoteType.type}`).then(res => res.json())    // finish up   console.log('done') }  getQuote()

Here is an animated explanation of this process.

See the Pen
Animated Description of Async Await
by Sarah Drasner (@sdras)
on CodePen.

Try, Catch, Finally

Eventually we’ll want to add error states to this process. We have handy try, catch, and finally blocks for this.

try {   // I’ll try to execute some code for you } catch(error) {   // I’ll handle any errors in that process }  finally {   // I’ll fire either way }

Let’s restructure the code above to use this syntax and catch any errors.

async function getQuote() {   try {     // get the type of quote from one fetch call, everything else waits for this to finish     let quoteType = await fetch(`quotes.json`).then(res => res.json())        // use what we got from the first call in the second call to an API, everything else waits for this to finish     let quote = await fetch(`programming-quotes.com/$  {quoteType.type}`).then(res => res.json())      // finish up     console.log('done')   }    catch(error) {     console.warn(`We have an error here: $  {error}`)   } }  getQuote()

We didn’t use finally here because we don’t always need it. It is a block that will always fire whether it is successful or fails. Consider using finally any time you’re duplicating things in both try and catch. I usually use this for some cleanup. I wrote an article about this, if you’re curious to know more.

You might eventually want more sophisticated error handling, such as a way to cancel an async function. There is, unfortunately, no way to do this natively, but thankfully, Kyle Simpson created a library called CAF that can help.

Not always blocking

Not all code within an async function will pause execution, the await keyword is the key to this. To explore this, let’s go over a pared-down example so you can see what the syntax looks like, as well as what the await is letting us do.

We’ll need the aid of a couple of helpers to illustrate the concept.

First, we’ll create a promise with a setTimeout. This little helper will basically just say, “Hey, wait around for the amount of time we pass in.” It will be called waitBy. This is very similar to the promise we used in the second example, written as a one-liner.

const waitBy = (duration) => new Promise(resolve => setTimeout(resolve, duration))

Second, we’ll make a small animation of a box that will last one second. Unlike our promised setTimeout helper, this little box animation will not pause any execution by default even though it happens over time.

function moveBox() {   gsap.to('.box', {     duration: 1,     x: 300,     rotation: 360,     ease: 'back'   }) }

The main Async function

Now let’s make our main async function. We’ll use the helper to wait three seconds and then log the output to the console.

Next, we’ll run our animation. Note how even though the animation doesn’t delay the final timing of the last waitBy function, even though it lasts for one second. That’s because it wasn’t await-ed.

The final waitBy function will still occur after another three seconds and then logs to the console.

async function mainDemo() {   // uses the helper above to wait 3 seconds   await waitBy(3000)   console.log('I will log after 3 seconds')      // moves the box for a second, but doesn't pause the execution   moveBox()      // uses the helper to wait for another 3 seconds, and then logs again   await waitBy(3000)   console.log('I will log after 6 seconds') }  mainDemo()
> I will log after 3 seconds > I will log after 6 seconds

See the Pen
Explain Async Await Visually
by Sarah Drasner (@sdras)
on CodePen.

Further Reading

It’s common for explanations of Async/Await to begin with callbacks, then promises, and use those explanations to frame Async/Await. Since Async/Await is well-supported these days, we didn’t walk through all of these steps. It’s still pretty good background, especially if you need to maintain older codebases. Here are some of my favorite resources out there:

The post Understanding Async Await appeared first on CSS-Tricks.

CSS-Tricks

, ,

Adding Dynamic And Async Functionality To JAMstack Sites

Jason Lengstorf:

Here’s an incomplete list of things that I’ve repeatedly heard people claim the JAMstack can’t handle that it definitely can:

  • Load data asynchronously
  • Handle processing files, such as manipulating images
  • Read from and write to a database
  • Handle user authentication and protect content behind a login

There is still a misconception that JAMstack = use a static site generator and that’s it, despite the fact that almost every article I’ve ever read about JAMstack gets into how it’s about pre-rendering what you can, and using client-side JavaScript and APIs to do the rest.

Phil laid that out very nicely for us recently.

This misconception seems very real to me. I hear it regularly. As I was writing this, I saw this question posted on Reddit.

Beginner question. Is JAM useful for applications or only for websites?

I’ll spare you from a speech about the uselessness of trying to distinguish between “apps” and “sites” but I think this helps make the point that there is plenty of confusion out there.


If you’re in a festive mood…

Tim Chase got creative and wrote this tongue-in-cheek poem. It’s obviously a joke but its assumption comes from the exact other angle, that JAMstack requires client-side JavaScript to do anything:

I do not like that stack that’s JAM
I do not like it, Sam-I-am.
I will not run it for a spell,
I will not use your GraphQL.
I will not run it over QUIC
No, Sam-I-am, it makes me sick.
Listen how it makes me cough
It does not work with JS off.

And Phil responded:

These thoughts make sense, I must agree
Except you really don’t need all three
It’s up to you. For you to choose.
JavaScript’s just an option you might use.
And if you do, success might be
From enhancing things progressively.

A JAMstack site might seem reliant
On doing everything in the client
In fact though, it depends on what
Requirements and use-cases you have got
The biggest key though, to remember
Is to serve things statically, and pre-render.

Direct Link to ArticlePermalink

The post Adding Dynamic And Async Functionality To JAMstack Sites appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]

Fetching Data in React using React Async

You’re probably used to fetching data in React using axios or fetch. The usual method of handling data fetching is to:

  • Make the API call.
  • Update state using the response if all goes as planned.
  • Or, in cases where errors are encountered, an error message is displayed to the user.

There will always be delays when handling requests over the network. That’s just part of the deal when it comes to making a request and waiting for a response. That’s why we often make use of a loading spinner to show the user that the expected response is loading.

See the Pen
ojRMaN
by Geoff Graham (@geoffgraham)
on CodePen.

All these can be done using a library called React Async.

React Async is a promised-based library that makes it possible for you to fetch data in your React application. Let’s look at various examples using components, hooks and helpers to see how we can implement loading states when making requests.

For this tutorial, we will be making use of Create React App. You can create a project by running:

npx create-react-app react-async-demo

When that is done, run the command to install React Async in your project, using yarn or npm:

## yarn yarn add react-async  ## npm npm install react-async --save

Example 1: Loaders in components

The library allows us to make use of <Async> directly in our JSX. As such, the component example will look like this;

// Let's import React, our styles and React Async import React from 'react'; import './App.css'; import Async from 'react-async';  // We'll request user data from this API const loadUsers = () =>   fetch("https://jsonplaceholder.typicode.com/users")     .then(res => (res.ok ? res : Promise.reject(res)))     .then(res => res.json())  // Our component function App() {   return (     <div className="container">       <Async promiseFn={loadUsers}>         {({ data, err, isLoading }) => {           if (isLoading) return "Loading..."           if (err) return `Something went wrong: $  {err.message}`            if (data)             return (               <div>                 <div>                   <h2>React Async - Random Users</h2>                 </div>                 {data.map(user=> (                   <div key={user.username} className="row">                     <div className="col-md-12">                       <p>{user.name}</p>                       <p>{user.email}</p>                     </div>                   </div>                 ))}               </div>             )         }}       </Async>     </div>   ); }  export default App;

First, we created a function called loadUsers. This will make the API call using the fetch API. And, when it does, it returns a promise which gets resolved. After that, the needed props are made available to the component.

The props are:

  • isLoading: This handles cases where the response has not be received from the server yet.
  • err: For cases when an error is encountered. You can also rename this to error.
  • data: This is the expected data obtained from the server.

As you can see from the example, we return something to be displayed to the user dependent on the prop.

Example 2: Loaders in hooks

If you are a fan of hooks (as you should), there is a hook option available when working with React Async. Here’s how that looks:

// Let's import React, our styles and React Async import React from 'react'; import './App.css'; import { useAsync } from 'react-async';  // Then we'll fetch user data from this API const loadUsers = async () =>   await fetch("https://jsonplaceholder.typicode.com/users")     .then(res => (res.ok ? res : Promise.reject(res)))     .then(res => res.json())  // Our component function App() {   const { data, error, isLoading } = useAsync({ promiseFn: loadUsers })   if (isLoading) return "Loading..."   if (error) return `Something went wrong: $  {error.message}`   if (data)      // The rendered component   return (     <div className="container">       <div>         <h2>React Async - Random Users</h2>       </div>       {data.map(user=> (         <div key={user.username} className="row">           <div className="col-md-12">             <p>{user.name}</p>             <p>{user.email}</p>           </div>         </div>       ))}     </div>   ); }  export default App;

This looks similar to the component example, but in this scenario, we’re making use of useAsync and not the Async component. The response returns a promise which gets resolved, and we also have access to similar props like we did in the last example, with which we can then return to the rendered UI.

Example 3: Loaders in helpers

Helper components come in handy in making our code clear and readable. These helpers can be used when working with an useAsync hook or with an Async component, both of which we just looked at. Here is an example of using the helpers with the Async component.

// Let's import React, our styles and React Async import React from 'react'; import './App.css'; import Async from 'react-async';  // This is the API we'll use to request user data const loadUsers = () =>   fetch("https://jsonplaceholder.typicode.com/users")     .then(res => (res.ok ? res : Promise.reject(res)))     .then(res => res.json())  // Our App component function App() {   return (     <div className="container">       <Async promiseFn={loadUsers}>           <Async.Loading>Loading...</Async.Loading>           <Async.Fulfilled>             {data => {               return (                 <div>                   <div>                     <h2>React Async - Random Users</h2>                   </div>                   {data.map(user=> (                     <div key={user.username} className="row">                       <div className="col-md-12">                         <p>{user.name}</p>                         <p>{user.email}</p>                       </div>                     </div>                   ))}                 </div>               )             }}           </Async.Fulfilled>           <Async.Rejected>             {error => `Something went wrong: $  {error.message}`}           </Async.Rejected>       </Async>     </div>   ); }  export default App;

This looks similar to when we were making use of props. With that done, you could break the different section of the app into tiny components.

Conclusion

If you have been growing weary of going the route I mentioned in the opening section of this tutorial, you can start making of React Async in that project you are working on. The source code used in this tutorial can be found in their different branches on GitHub.

The post Fetching Data in React using React Async appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]