我是javascript的新手,如果您误解了该语言是如何处理某些事情的, 我正在构建一个排序算法可视化程序,该可视化程序按色相值对块进行排序(使用chroma-js库): screenObject.items中的每个项目都是一个Color对象
//color objects are what I am sorting
class Color {
constructor(div, color, value) {
//this div on the html page
this.div = div;
this.color = color;
//hue value of the color
this.value = value;
}
update(color, value) {
this.color = color;
this.value = value;
this.div.style.backgroundColor = color;
}
}
class ScreenObject {
constructor() {
//this is an array of color objects
this.items = [];
}
bubbleSort() {
let solved = false;
while (!solved) {
let swaps = 0;
this.items.forEach((item, index) => {
if (index > 0) {
swaps += compare(this.items[index - 1], item);
}
});
if (swaps === 0) {
solved = true;
}
}
}
}
function compare(color1, color2) {
if (color1.value > color2.value) {
swap(color1, color2);
return 1;
} else {
return 0;
}
}
function swap(color1, color2) {
colorStore = color1.color;
valueStore = color1.value;
color1.update(color2.color, color2.value);
color2.update(colorStore, valueStore);
}
我遇到的问题是,仅在程序完成后才更新颜色,如果我添加setIterval或setTimeout,则只能在每次通过后进行颜色更新,而不是在每次比较/交换之后进行更新(在比较颜色时,我想添加特殊的样式):
bubbleSort() {
let solved = false;
while (!solved) {
let swaps = 0;
setInterval(() => {
this.items.forEach((item, index) => {
if (index > 0) {
swaps += compare(this.items[index - 1], item);
}
});
}, 50);
if (swaps === 0) {
solved = true;
}
}
}
我希望能够在每次比较后看到颜色更新,例如swap(1,2),用户看到1得2的颜色和2得1的颜色。
谢谢!
答案 0 :(得分:0)
我将假设您正在浏览器上执行此操作。您需要让事件循环回去,以便发生其他事情,例如重新绘制页面。可能最简单的事情是使您的bubbleSort
成为async
方法,并使其await
一些东西,例如计时器回调:
async bubbleSort() { // <=== Note the `async`
let solved = false;
while (!solved) {
let swaps = 0;
// *** No `setInterval`
for (const [index, item] of this.items.entries()) {
if (index > 0) {
const result = compare(this.items[index - 1], item);
if (result) { // *** Did it do something?
swaps += result;
await delay(0); // *** Wait for it to be redrawn
}
}
});
if (swaps === 0) {
solved = true;
}
}
}
...其中delay
可能是:
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
调用bubbleSort
时,它将几乎立即返回一个承诺,并异步继续其逻辑直到完成,然后兑现该承诺。
请注意,在ES2018中添加了async
函数。现代浏览器已经很好地支持了这一功能,但您可能需要像Babel这样的工具才能将其移植到较旧的浏览器中。
如果您想更加精确,可以将requestAnimationFrame
而不是setTimeout
设为零长度超时。这是一个有点违反直觉的功能:
const nextFrame = (cb = () => {}) => new Promise(resolve => {
requestAnimationFrame(() => {
cb();
resolve();
});
});
...您将用来代替delay
的
await nextFrame();
(在您的情况下,您无需传递任何回调,默认的不执行回调就足够了。)
我在this tweet中解释了对该函数进行奇数设计的原因(这反过来又询问是否真的需要对它进行奇数设计)。
另一种方法是稍微反转逻辑并使用生成器函数来生成每个交换。然后,您可以循环驱动该发电机。这就是我使用的when answering this other question about visualizing buble sort方法。