简体   繁体   English

JavaScript 一个接一个地运行一个函数

[英]JavaScript run one function after another

I am trying to create a visual selection sort.我正在尝试创建一个视觉选择排序。 finMin() will go through the array one by one displaying the new min when found. finMin()将一一遍历数组,在找到时显示新的最小值。 I want to use this function in a loop for selection sort.我想在循环中使用此函数进行选择排序。 If the function is run one time, then everything is fine, but if findMin() is run in a loop, then the function has bugs.如果该函数运行一次,则一切正常,但如果findMin()循环运行,则该函数有错误。

If a function is run in a loop such as for(let i=0; i<3; i++){findMin();} does the second iteration of the loop run immediately or does it wait for findMin to return before i == 1 ?如果一个函数在循环中运行,例如for(let i=0; i<3; i++){findMin();}是立即运行循环的第二次迭代还是等待findMini == 1之前返回i == 1 ? I believe that this loop should be sequential, but I do not know why the code does not work in a loop then.我相信这个循环应该是顺序的,但我不知道为什么代码在循环中不起作用。

 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>

What you want to do is use JavaScript Promises.你想要做的是使用 JavaScript Promises。 ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise ) There you have a concept called chaining so that you can chain your functions one after the other based on execution (in this case resolved). ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise ) 你有一个叫做链接的概念,这样你就可以根据执行一个接一个地链接你的函数(在这种情况下解决)。 For an example Let say you have to functions:例如,假设您必须执行以下操作:

function a() {
  setTimeout( function() {
    resolve("Success!")  // Yay! Everything went well!
  }, 250) 
}  

function b() {
  setTimeout( function() {
    resolve("Success 2!")  // Yay! Everything went well!
  }, 250) 

}

you can make these promises and chain them one after the other:你可以做出这些承诺并将它们一个接一个地链接起来:

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();
}); 

setTimeout returns a number representing the id of the timer, so when running findMin() in a loop it will return that, and immediately after execute the next iteration. setTimeout 返回一个表示计时器 id 的数字,因此在循环中运行 findMin() 时,它将返回该值,并在执行下一次迭代后立即返回。

To make the loop wait for the timeout you'll have to await for a promise that is resolved after the delay要使循环等待超时,您必须等待延迟后解决的承诺

for (let i = 0; i < 3; i++) {
  min = await new Promise((resolve) => {
    setTimeout(() => {
      resolve(timeout(i, min))
    }, 500);
  })
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM