如何在每次循环迭代中更新DOM?

时间:2018-01-02 11:38:59

标签: javascript dom

我有以下课程:

// Population class
class Population {

    constructor(size, target, mutationRate, minFitness) {
        this.target = target;
        this.size = size;
        this.individuals = [];
        // contains phrases (strings)
        this.matePool = [];
        this.mutationRate = mutationRate;
        this.bestFitness = 0;
        this.bestPhrase = "";
        this.totalGenerations = 0;
        // Stopping criterion
        this.minFitness = minFitness;
    }

    clearMatePool () {
        this.matePool = [];
    }

    addIndividual(newIndividual) {
        this.individuals.push(newIndividual);
    }

    evaluate() {
        let fitness = 0;
        for (let i = 0; i < this.size; i++) {
            fitness = this.individuals[i].fitnessFunct(this.target);
            // Update best fitness and best phrase
            if (fitness > this.bestFitness) {
                this.bestFitness = fitness;
                this.bestPhrase = this.individuals[i].getGenotype();
            }
        }
        // Stopping criterion
        if (this.bestFitness < this.minFitness) {
            return true;
        }
        else {
            return false;
        }
    }

    buildMatePool() {
        for (let i = 0; i < this.size; i++) {
            let n = Math.round(this.individuals[i].getFitness() * 100);
            for (let j = 0; j < n; j++) {
                this.matePool.push(this.individuals[i].phrase);
            }
        }
    }

    reproduce() {
        // Create new generation
        for (let i = 0; i < this.size; i++) {
            // Pick 2 parents
            let a, b, child, midpoint;
            while (true) {
                // Index of parentA
                a = getRandomIntInclusive(0, this.matePool.length - 1);
                // Index of parentB
                b = getRandomIntInclusive(0, this.matePool.length - 1);
                // Be sure you have picked two unique parents (phrases)
                if (this.matePool[a] === this.matePool[b]) {
                    continue;
                }
                else {
                    break;
                }
            }
            // Crossover
            child = this.crossover(a, b);
            // Mutation
            this.mutation(child);
            // The new child is part of the new population
            this.individuals[i] = child;
        }
        this.totalGenerations += 1;
    }

    crossover(a, b) {
        let child = new Individual(this.target.length);
        child.setGenotype("");
        let midpoint = getRandomIntInclusive(0, this.target.length-1);

        for (let i = 0; i < this.target.length; i++) {
            if (i < midpoint) {
                child.phrase = child.phrase + this.matePool[a].charAt(i);
            }
            else {
                child.phrase = child.phrase + this.matePool[b].charAt(i);
            }
        }
        return child;
    }

    mutation(individual) {
        for (let i = 0; i < this.target.length; i++) {
            // The block inside the conditional statement would be executed 1% of the time.
            if(Math.random() < this.mutationRate) {
                // replace char with a new random character
                individual.phrase = individual.phrase.substr(0, i) + String.fromCharCode(getRandomIntInclusive(32, 128)) + individual.phrase.substr(i + 1);
            }
        }
    }

}

我有以下DOM元素:

// Shows the current generation
var totalGenerationsHTML = $('#total-generations');
// Shows the best phrase so far
var bestPhraseHTML = $('#best-phrase');
// Shows the best fitness so far
var bestFitnessHTML = $('#best-fitness');
// Shows the result of the reproduction process (child)
var processingHTML = $('#processing');

以下代码部分:

var condition = population.evaluate();

while (condition) {
    // Processing
    population.buildMatePool();
    population.reproduce();
    population.clearMatePool();
    condition = population.evaluate();
}

我需要在每次迭代中更新DOM元素的值。我尝试使用 setInterval() setTimeout()进行不同的循环实现,但输出不同步。任何帮助都会有用。

P.S。我是JavaScript的新手。请原谅任何错误。

2 个答案:

答案 0 :(得分:0)

while (condition) {}

所谓的阻塞代码,因为该循环在没有给浏览器实际渲染结果的情况下运行,你不会看到任何东西,可能是UI冻结。

您需要使用setTimeoutsetInterval或建议动画requestAnimationFrame

  

但输出不同步

更改DOM以及页面上的可见内容是异步进程,而Js正在运行时,浏览器不会重新绘制。 while循环正在运行JS。

有关详细信息,请查看here

答案 1 :(得分:0)

@philipp是对的。 setInterval(updateMarquee(), 10000);是解决方案。

基本上requestAnimationFrame()是:

  1. 与浏览器重绘同步(requestAnimationFrame()setTimeout不是)
  2. 针对动画进行了优化
  3. 以屏幕允许的速度运行
  4. 电池保护程序
  5. 以下HTML / JS / CSS代码段演示了setInterval

    的使用

    requestAnimationFrame()
    var currentPos = -200;
    
    var element = document.getElementById("heading");
    
    // Animation loop
    function moveRight() {
      currentPos += 5;
    	heading.style.left = currentPos + "px";
    	window.requestAnimationFrame(moveRight);
    	if(currentPos >= 800) {
    	  currentPos = -200;
    	}
    }
    
    moveRight();
    h1 {
      position: relative;
      border: 5px solid black;
      text-align: center;
      width: 200px;
    }
    
    div {
      width: 800px;
      height: 400px;
      background-color: lime;
      margin: 0 auto;
      overflow: hidden;
    }