Piszemy własną pętlę for. Uczymy się tworzyć asynchroniczne procesy. Wstęp do napisania własnej klasy promise.

Na początku stany:

const STATE = {
    PENDING: 'PENDING',
    FULFILLED: 'FULFILLED',
  }

Teraz konstruktor, który bierze init, max, iter oraz callback (bloki budulcowe każdej pętli for):

class Loop {

    constructor(init, max, iter, callback) {

        this.state = STATE.PENDING;
        this.init = init;
        this.max = max;
        this.iter = iter;
        this.callback = callback;
       
      }
}

Metoda start:

class Loop {
   
   /(...)
 
   start(){
      this.updateResult(this.init, STATE.PENDING);
    }
}

Rozpoczęcie procesu pętli (bez opóźnienia):

class Loop {
      
      //(...)
      
      updateResult(value, state) {
        setTimeout(() => {
          this.state = state;
          
          //(...)
          
        }, 0);
      }
}

Sprawdzenie, czy stan się zgadza i czy warunek nie został spełniony:

class Loop {
      
      updateResult(value, state) {
        setTimeout(() => {
          this.state = state;
          
          if (this.state !== STATE.PENDING) {
            return;
          }

          if(value >= this.max){
            this.state === STATE.FULFILLED;
            return;
          }

          //(...)
          
        }, 0);
      }
}

Callback, zwiększenie iter o iter, następny krok:

class Loop {
      
      //(...)
       
      updateResult(value, state) {
        setTimeout(() => {
          this.state = state;
          
          if (this.state !== STATE.PENDING) {
            return;
          }

          if(value >= this.max){
            this.state === STATE.FULFILLED;
            return;
          }

          this.callback(value);

          this.init += this.iter;

          this.updateResult(this.init, STATE.PENDING);
          
        }, 0);
      }
}

Przykład użycia:

let loop = new Loop(0,3,1,(num) => console.log(num));

loop.start();

//0
//1
//2