im using Vanilla Javascript, and my problem is that i need to render a progress bar in a certain time, but JS only render the final step...
'use strict'
var button = document.getElementById('button');
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
function initProgressBar()
{
let progressBar = document.querySelector('#progress-bar'),
count = 25,
total = 64;
progressBar.style = `width:${count}%;`;
while (total > 0) {
sleep(300);
total = Math.trunc(total/2);
count = count total;
progressBar.style = `width:${count}%;`;
}
}
button.onclick = initProgressBar;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#progress-container {
height: 4px;
width: 100%;
}
#progress-bar {
width: 0%;
height: 100%;
background-color: blueviolet;
}
</style>
</head>
<body>
<div id="progress-container">
<div id="progress-bar"></div>
</div>
<button id=button>press</button>
<script src='prueba.js'></script>
</body>
</html>
The idea is that when the user clicks the button, the progress bar automatically jumps to 25% and then progressively goes to ~ 88% (after that I'll send it to 100% using another function)
The problem is that Javascript only update the element on his last value (88%).
So, is there any way to set the attribute of an element multiple times inside a javasciript function?
CodePudding user response:
The source of the problem is likely the total = Math.trunc(total/2);
construction. You're dividing by 2 and then rounding down.
So it's goal is preset to 25 64 = 89
, meaning 89% is the end.
Once it gets to 88%, it takes that remaining 1, divides it by 2 (1 / 2 = 0.5
) and then it rounds that down, so it becomes 0, 88 0 = 88
, which still isn't 89, so it'll just end up in an infinite loop there.
CodePudding user response:
The way sleep
will block the execution thread and might lead to unexpected behaviour in some cases. A better implementation of sleep could be done using Promise and setTimeout.
Here's the snippet using the modified sleep
, that works as expected :
'use strict'
var button = document.getElementById('button');
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function initProgressBar()
{
let progressBar = document.querySelector('#progress-bar'),
count = 25,
total = 64;
progressBar.style = `width:${count}%;`;
while (total > 0) {
await sleep(300);
total = Math.trunc(total/2);
count = count total;
progressBar.style = `width:${count}%;`;
}
}
button.onclick = initProgressBar;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#progress-container {
height: 4px;
width: 100%;
}
#progress-bar {
width: 0%;
height: 100%;
background-color: blueviolet;
}
</style>
</head>
<body>
<div id="progress-container">
<div id="progress-bar"></div>
</div>
<button id=button>press</button>
<script src='prueba.js'></script>
</body>
</html>