我正在使用 JavaScript 制作排序算法可视化工具。我已经把大部分内容都放下了,但目前,在排序完成之前,条形图不会显示,此时,它确实显示已排序。
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sorting Algorithm Visualizer</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="controls">
<select id="algorithm">
<option value="bubble">Bubble Sort</option>
<option value="selection">Selection Sort</option>
</select>
<input type="text" id="Size" value=10>
<button onclick="gen()">Generate</button>
<input type="number" id="delay" min="0" value="1"> (ms delay)
</div>
<div class="bars" id="setup"></div>
<script src="script.js"></script>
</body>
</html>
CSS:
.bars{
background-color: black;
width: 10px;
height: 10px;
position: absolute;
bottom: 100%;
margin: 0px;
visibility: hidden;
}
JavaScript:
var list;
var ind;
var size;
var sort;
var delay;
var count;
const content = document.getElementById("content");
var height = Math.floor(window.innerHeight * 0.9);
var width = Math.floor(window.innerWidth);
function swap(arr, a, b) {
[arr[a], arr[b]] = [arr[b], arr[a]];
update(a);
update(b);
}
function bubbleSort(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < (arr.length - i - 1); j++) {
sleep(delay);
if (arr[j] > arr[j + 1]) {
swap(list, j, j + 1);
}
}
}
console.log(list);
}
function shuffle(arr) {
ind = list.length - 1;
for (var i = arr.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
swap(arr, i, j);
}
}
function update(item) {
const bar = document.getElementById("bar" + item);
if (bar) {
bar.style.visibility="visible";
bar.style.height = (height / size) * list[item] + "px";
}
}
function createBars(arr) {
count = 0;
while (count < arr.length) {
var bar = document.createElement('div');
bar.classList.add("bars");
bar.setAttribute('id', "bar" + count);
document.body.appendChild(bar);
bar.style.width = Math.round(width / size) + "px";
bar.style.visibility = "visible";
bar.style.bottom = "0%";
bar.style.left = count * width / size + "px";
bar.style.height = (height / size) * arr[count] + "px";
count++;
updateAll();
}
}
function gen() {
if (list != undefined) {
var element = document.getElementById("parent");
element.textContent = "";
}
list = [];
size = document.getElementById("Size").value;
for (count = 1; count <= size; count++) {
list.push(count);
}
shuffle(list);
createBars(list);
sleep(1000);
sort = document.getElementById("algorithm").value;
delay = document.getElementById("delay").value;
if (sort == "bubble") {
bubbleSort(list);
}
}
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function updateAll() {
for (let i = 0; i < list.length; i++) {
update(list, i);
}
}
抱歉长度太长了。
我期望发生的是在 createBars() 函数完成后会显示条形图,但这并没有发生。我希望能够看到条形变化高度以匹配“列表”数组的相应项目。这并没有发生。有谁知道这个问题的可能解决办法吗?
Javascript 是单线程环境(有一些超出范围的例外)。这意味着执行 js 的同一线程也用于渲染 html。这个单线程需要在某些点释放,以便发生视觉变化
这段代码中的
sleep
方法实际上做了与sleep相反的事情。它将线程捆绑在循环中进行不必要的计算
实现更好
sleep
的一种方法是使用 setTimeout
、promise 和 async
/await
// create a promise that will "resolve" after milliseconds
function sleep(milliseconds) {
return new Promise(resolve => {
setTimeout(resolve, milliseconds)
})
}
sleep 方法将立即返回一个 Promise,并且调用代码可以
await
该 Promise。 await
时间将是milliseconds
时间。 await
的好处是释放了单线程,这样UI就可以开始渲染了
这是如何使用新功能的示例
sleep
// enable the await keyword by making this function async
async function bubbleSort(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < (arr.length - i - 1); j++) {
// await the sleep method
await sleep(delay);
if (arr[j] > arr[j + 1]) {
swap(list, j, j + 1);
}
}
}
console.log(list);
}
async
和await
具有传染性。这意味着每个使用 async
函数的函数本身也需要更改为 async
。所以很多代码需要异步化
async
/await
一开始可能有点难以理解,所以如果您遇到困难,我建议您阅读一些有关该主题的内容
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function