Reputation: 211
I have a async function with await fetch. I want to show a loading icon to user till the await completes and then show the next div.
let getOTP = await fetch(url, {
method: 'POST',
headers: {
"Content-Type": "text/plain"
},
body: JSON.stringify({
"Number": mobileNumber
})
});
let data = await getOTP.json();
let errorCode = data.errorCode;
if (errorCode == 0) {// show next div}
I have tried used setTimeout(function (){},5000) functions set to 5 seconds (or more) but sometimes it takes longer for the reply to come. So, How do I show a loading icon till the await completes ?
Upvotes: 10
Views: 21246
Reputation: 1426
Simply display loader before fetch, and remove it after await
.
const fetchButton = document.querySelector('#fetchButton')
const loader = document.querySelector('#loader')
const content = document.querySelector('#content')
function fetchData() {
// Here should be your api call, I`m using setTimeout here just for async example
return new Promise(resolve => setTimeout(resolve, 2000, 'my content'))
}
fetchButton.onclick = async function () {
content.innerHTML = ''
// Your loader styling, mine is just text that I display and hide
loader.style.display = 'block'
const nextContent = await fetchData()
loader.style.display = 'none'
content.innerHTML = nextContent
}
<button id="fetchButton">Fetch</button>
<div id="loader" style="display: none">Loading...</div>
<div id="content"></div>
Upvotes: 11
Reputation: 3502
Start the loading image in the beginning of your code and stop it when there is no error and your code enter in the (errorCode == 0)
condition.
<-- START loading Here -->
let getOTP = await fetch(url, {
method: 'POST',
headers: {
"Content-Type": "text/plain"
},
body: JSON.stringify({
"Number": mobileNumber
})
});
let data = await getOTP.json();
let errorCode = data.errorCode;
if (errorCode == 0) {
<-- STOP loading Here -->
}else{
<-- STOP loading Here on error -->
}
Upvotes: 0
Reputation: 28499
Just put the code to hide the icon after the line that calls await
. Use try
/ finally
to make sure that the code is also executed when something goes wrong in your asynchronous call.
You can encapsulate this mechanism in a function like the WithIcon
function as shown below to reuse it at different places.
// Test function
async function test()
{
await WithIcon(timeout(3000));
testAfterAction();
}
function testAfterAction()
{
var elem = document.createElement('div');
elem.innerText = "Some text";
document.body.appendChild(elem);
}
// Use setTimeout to symulate some asynchronous i/o operation
function timeout(ms)
{
return new Promise(resolve => setTimeout(resolve, ms));
}
// While awaiting the promise, show a wait icon
async function WithIcon(promise)
{
ShowAwaiting();
try
{
await promise;
}
finally
{
HideAwaiting();
}
}
// To only hide the icon when every ShowAwaiting call was met with a HideAwaiting call
var globalAwaitingCounter = 0;
// Show wait icon
function ShowAwaiting()
{
if(globalAwaitingCounter <= 0)
{
document.getElementById("awaiting").style.display = "inline";
globalAwaitingCounter = 1;
}
else
{
globalAwaitingCounter++;
}
}
// Hide wait icon
function HideAwaiting()
{
if(globalAwaitingCounter <= 1)
{
document.getElementById("awaiting").style.display = "none";
globalAwaitingCounter = 0;
}
else
{
globalAwaitingCounter--;
}
}
<html>
<body>
<button type="button" onclick="test();">Test</button>
<span id="awaiting" style="display:none">Awaiting....</span>
</body>
</html>
Upvotes: 0