首页 > 解决方案 > 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

解决方案


你想要做的是使用 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();
}); 


推荐阅读