javascript - JavaScript 一个接一个地运行一个函数
问题描述
我正在尝试创建一个视觉选择排序。finMin()
将一一遍历数组,在找到时显示新的最小值。我想在循环中使用这个函数进行选择排序。如果该函数运行一次,那么一切都很好,但如果findMin()
在循环中运行,则该函数有错误。
如果一个函数在循环中运行,例如循环for(let i=0; i<3; i++){findMin();}
的第二次迭代是立即运行还是等待findMin
返回之前i == 1
?我相信这个循环应该是顺序的,但我不知道为什么代码在循环中不起作用。
var gBars = [];
var gSelected = 19;
var gFinished = 19;
var changed = false;
var step = 0;
function Bar(index, height){
this.index = index;
this.height = height;
this.getIndex = function(){
console.log(this.index);
};
this.getHeight = function(){
console.log(this.height);
};
this.getStats = function(){
console.log(this.index + ' ' + this.height);
}
this.setHeight = function(h){
this.height = h;
}
this.setIndex = function(i){
this.index = i;
}
}
function insertAfter(newNode, referenceNode){
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
function setHeight(i, h){
document.getElementById(i).style.height = h + 'em';
}
function addBar(i, h){
//base case i = 0
//first bar
if(i === 0){
var currentDiv = document.getElementById("root");
d = document.createElement('div');
d.setAttribute("id", 'block'+i);
d.setAttribute("class", 'block');
gBars[i] = new Bar(i, h);
currentDiv.appendChild(d);
setHeight('block'+i,h);
}
else {
let last = i-1;
var currentDiv = document.getElementById('block'+last);
d = document.createElement('div');
d.setAttribute("id", 'block'+i);
d.setAttribute("class", 'block');
gBars[i] = new Bar(i, h);
insertAfter(d, currentDiv);
setHeight('block'+i,h);
}
}
function selSort(){
for(let i=0; i<10; i++){
findMin(gFinished);
}
}
function findMin(gFinished) {
let min = gBars[gFinished].height;
//start at 18 because bars are rotated 180deg
//go backwards so it appears to go forwards
var delay = 500;
let i = gFinished - 1;
min = setTimeout(timeout(i, min), delay);
return min;
}
function timeoutchange(){
var swapped = document.getElementById('block'+gFinished);
var selected = document.getElementById('block'+gSelected);
let temp = gBars[gFinished].height;
swapped.style.height = gBars[gSelected].height + 'em';
selected.style.height = temp + 'em';
selected.style.backgroundColor = "grey";
var selected = document.getElementById('block'+gFinished);
selected.style.backgroundColor = "green";
gFinished--;
var selected = document.getElementById('block'+gFinished);
selected.style.backgroundColor = "blue";
gSelected = gFinished;
}
function timeout(i, min) {
console.log("Next loop: " + i);
if(i==18){
var selected = document.getElementById('block19');
selected.style.backgroundColor = "blue";
}
if(min > gBars[i].height) {
min = gBars[i].height;
var selected = document.getElementById('block'+i);
selected.style.backgroundColor = "blue";
console.log('new min ' + min);
selected = document.getElementById('block'+gSelected);
selected.style.backgroundColor = "grey";
gSelected = i;
}
i--;
if (i == 0) {
console.log("End");
var swapped = document.getElementById('block'+gFinished);
swapped.style.backgroundColor = "red";
setTimeout(function(){
return timeoutchange();
},1000)
step++;
return min;
} else {
setTimeout(function(){
return timeout(i, min);
},500)
}
}
function init(){
for(let i=0; i<20; i++){
let ran = Math.floor(Math.random() * 50 + 1);
gBars[i] = new Bar(i,ran);
addBar(i,ran);
}
for(let i=0; i<20; i++){
gBars[i].getStats();
}
//works
findMin(gFinished);
//findMin does not work in loop
//why?
//selSort();
return;
}
init();
.selected{
background-color:blue;
}
.block{
border:1px solid rgba(0,0,0,.4);
width:20px;
background-color:grey;
}
#root{
display:flex;
transform:rotate(180deg);
position:absolute;
left:10%;
}
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<button>sort</button>
<div id="root"></div>
</body>
<script src="selectionsort.js"></script>
</html>
解决方案
你想要做的是使用 JavaScript Promises。(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)您有一个称为链接的概念,以便您可以根据执行一个接一个地链接您的函数(在这种情况下解决)。例如,假设您必须执行以下操作:
function a() {
setTimeout( function() {
resolve("Success!") // Yay! Everything went well!
}, 250)
}
function b() {
setTimeout( function() {
resolve("Success 2!") // Yay! Everything went well!
}, 250)
}
您可以做出这些承诺并将它们一个接一个地链接起来:
let a = new Promise((resolve, reject) => {
setTimeout( function() {
resolve("Success!") // Yay! Everything went well!
}, 250)
})
let b = new Promise((resolve, reject) => {
setTimeout( function() {
resolve("Success2!") // Yay! Everything went well!
}, 250)
})
let c = new Promise((resolve, reject) => {
setTimeout( function() {
resolve("Success3!") // Yay! Everything went well!
}, 250)
})
a().then(()=>{
return b();
}).then(()=>{
return c();
});
推荐阅读
- android - 通过网络链接/html/web 应用程序启动已安装的第三方 Android 应用程序?
- python - 在散景图之间共享 x 轴
- javascript - 如何访问不同目录中的本地 json 文件而不会出现 404 错误?
- meteor - 从 MeteorJS 获取 mp3 文件并尝试将其转换为 Blob 以便我可以播放它
- c - 仅替换用户在 c 中输入的零
- javascript - 在 Typescript 原始函数中访问“this”
- python - 当用户导入已弃用的变量时引发自定义 ImportError
- android - 无法从嵌套静态类访问复选框对象
- sql - 在 Oracle 中删除对象后权限丢失
- sql-server - LOG_BACKUP 文件已满时无法备份数据库