簡體   English   中英

JavaScript 一個接一個地運行一個函數

[英]JavaScript run one function after another

我正在嘗試創建一個視覺選擇排序。 finMin()將一一遍歷數組,在找到時顯示新的最小值。 我想在循環中使用此函數進行選擇排序。 如果該函數運行一次,則一切正常,但如果findMin()循環運行,則該函數有錯誤。

如果一個函數在循環中運行,例如for(let i=0; i<3; i++){findMin();}是立即運行循環的第二次迭代還是等待findMini == 1之前返回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();
}); 

setTimeout 返回一個表示計時器 id 的數字,因此在循環中運行 findMin() 時,它將返回該值,並在執行下一次迭代后立即返回。

要使循環等待超時,您必須等待延遲后解決的承諾

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