1đź‘Ť
Your “loading” animation is “frozen” because JavaScript is single-threaded and when your transformation code is running (assuming there are much more data than shown in the example so it is running for significant amount of time), browser’s rendering is blocked.
Either you can optimize the transformation code to make it faster or you can take a look at this SO answer for details and solutions how to make long running operations not to block browser’s rendering….
- [Vuejs]-ReCAPTCHA v3 with vue-recaptcha-v3 (v1.8.0) constantly failing verification with the fetch API
- [Vuejs]-Vue Enter/Leave Transition doesn't seem to work well with Opacity
0đź‘Ť
I guess the problem is that you set loading to false before axios is done getting your data (because that is the only async operation in the code).
The .forEach
could probably be optimized a bit, but I doubt that is the culprit.
Try moving all your code in the .then
chained off of the axios.get()
instead.
- [Vuejs]-Installing TypeScript w/Vue CLI returns *Cannot find module 'eslint-plugin-@typescript-eslint'*
- [Vuejs]-Reactivity issue in vue component
0đź‘Ť
I can’t really speak to the efficiency of your code, but a simple way to keep a loading indicator going until after an async operation finishes, is to to stop it in a finally
-block:
const btn = document.getElementById('btn');
const mockLoadIndicator = document.getElementById('loading');
const data = [
{
"name": "bob",
"group": "A"
}, {
"name": "sally",
"group": "A"
}, {
"name": "john",
"group": "B"
}, {
"name": "jane",
"group": "B"
}
];
const mockAPI = () => {
mockLoadIndicator.style.display = 'block';
return new Promise((resolve) => {
setTimeout(() => resolve(data), 1000);
});
};
btn.onclick = () => mockAPI()
.then(console.log)
.finally(() => {
mockLoadIndicator.style.display = 'none';
});
#loading {
position: relative;
display: none;
height: 10px;
width: 10px;
border-radius: 50%;
background: grey;
animation-duration: 300ms;
animation-name: load;
animation-iteration-count: infinite;
animation-direction: alternate;
}
@keyframes load {
from {
left: 10px;
}
to {
left: 40px;
}
}
<button id="btn">Get Data</button>
<div id="loading"></div>