Introduction
In the last part, I used then
to set the src
attribute on the image tag directly.
// inside a click event handler
getImage(url)
.then(result => {
img.setAttribute('src', result)
})
.catch(err => console.log(err));
But sometimes it's useful to store the result of an await
ed promise in a variable. For instance it might be necessary to query part of a database, store the result in a variable, query a different source, and then combine the results.
How do you do that? The above situation doesn't really work. What's needed is a way to let the async
function return the result you want without necessarily chaining a then
after it.
Setup
Let's keep everything the same as before...
HTML
The markup for this is (still) going to be very straightforward.
<div>
<img src='' />
<button>Get a random image</button>
</div>
Javascript
The first part here can be exactly the same as before with one exception. The event listener needs to be async
. Feel free to look at the previous post if you need a refresher.
Event Listener
const img = document.querySelector('img')
const button = document.querySelector('button')
const div = document.querySelector('div')
const url = 'https://source.unsplash.com/random'
button.addEventListener('click', async () => {
console.log('click');
});
async/await
Now it's time to create a function that will do what we want. We'll start with the same declaration as before.
const img = document.querySelector('img')
const button = document.querySelector('button')
const div = document.querySelector('div')
const url = 'https://source.unsplash.com/random'
const getImage = async (url) => {
// handle awaiting the request and errors
}
button.addEventListener('click', async () => {
console.log('click');
});
The difference is that instead of chaining then
and catch
to the function, everything needs to be handled inside it. To do that, first create a try/catch
block.
const getImage = async (url) => {
try {
// handle a success
} catch (err) {
// catch errors and do something
}
}
The next thing to do is allow the function to return something. Fortunately try/catch
sets up it's own block context we can use to advantage.
const getImage = async (url) => {
let result;
try {
// fetch the result of getting the image from the endpoint.
const fetched = await fetch(url);
// set the value of result equal to the src url
result = fetched.src;
// return the result
return result;
} catch (err) {
// catch errors and do something
console.error(`something bad happened -> ${err}`)
}
}
Now when the button is clicked, the getImage
function can be run and stored as a variable.
const img = document.querySelector('img')
const button = document.querySelector('button')
const div = document.querySelector('div')
const url = 'https://source.unsplash.com/random'
const getImage = async (url) => {
let result;
try {
// fetch the result of getting the image from the endpoint.
const fetched = await fetch(url);
// set the value of result equal to the src url
result = await fetched.src;
// return the result
return result;
} catch (err) {
// catch errors and do something
console.error(`something bad happened -> ${err}`)
}
}
button.addEventListener('click', async () => {
const imgSrc = await getImage(url);
// set the image's src attribute to the returned url
img.setAttribute('src', imgSrc);
});
Handling failure
In this case, the error handling occurs inside the try/catch
block so that's where you could do something to show the user a problem occurred.
Conclusion
I don't think there's too much more to say here!