KaSkuLL
KaSkuLL

Reputation: 551

Recursive method with setTimeout

I'm trying to create a js object with a method which will print letter by letter with a 5 sec delay between each letter. But right now is not running. It writes it with no delay. Where is my error?

class autoWrite{
    constructor(id,text){
        this.id = id;
        this.text = text;
    }
    startTyping(index=0){
        if(index==this.text.length){
            console.log("finish");
        }
        else{
            $("#"+this.id).append(this.text.charAt(index));
            setTimeout(this.startTyping(index+1),5000);
        }
    }
}
 a = new autoWrite("body-window","hello world");
 a.startTyping();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
 <div id="body-window">

</div>

Upvotes: 1

Views: 98

Answers (3)

Niladri Basu
Niladri Basu

Reputation: 10614

Do this instead:

 class autoWrite{
        constructor(id,text){
            this.id = id;
            this.text = text;
        }
        startTyping(index=0){
            if(index==this.text.length){
                console.log("finish");
            }
            else{
                $("#"+this.id).append(this.text.charAt(index));
                console.log(this.text.charAt(index))
                setTimeout(() => this.startTyping(index+1), 500);
            }
        }
    }
    
    
    a = new autoWrite("body-window","hello world");
    a.startTyping();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
 <div id="body-window">

</div>

Alternatively, you can use setInterval() like this (better approach):

 class autoWrite{
        constructor(id,text){
            this.id = id;
            this.text = text;
            this.index = 0;
        }
        startTyping(){
            if(this.index==this.text.length){
                console.log("finish");
                this.index += 1;
            } else {  $("#"+this.id).append(this.text.charAt(this.index));
                console.log(this.text.charAt(this.index));
                this.index += 1;
            }
        }
        start(){
           setInterval(() => {
             if(this.index <= this.text.length){
               this.startTyping();
             }
           }, 500);
          
        }
    }
    
    
    a = new autoWrite("body-window","hello world");
    a.start();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
 <div id="body-window">

</div>

Upvotes: 3

Aayush Sharma
Aayush Sharma

Reputation: 839

As stated in the documentation of setTimeout by MDN here, the first argument is the reference to the function you need to execute after the delay.

You can use the following code.

class autoWrite{
    constructor(id,text){
        this.id = id;
        this.text = text;
    }
    startTyping(index=0){
        if(index==this.text.length){
            console.log("finish");
        }
        else{
            $("#"+this.id).append(this.text.charAt(index));
			let obj = this;
            setTimeout(function () {
				obj.startTyping(index+1);
            },5000);
        }
    }
}
 a = new autoWrite("body-window","hello world");
 a.startTyping();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
 <div id="body-window">

</div>

Upvotes: 1

hsz
hsz

Reputation: 152216

With

setTimeout(this.startTyping(index+1),5000);

you're passing the result of startTyping as a function to be invoked with setTimeout - which is undefined - it is also invoked immediately with no delay. Try with:

var that = this;
setTimeout(function() {
  that.startTyping(index+1);
}, 5000);

Upvotes: 5

Related Questions