How to wait for some time before executing next line of code in javascript

I am building a memory game in JS.
So far I can check that the card are matched or not .
All the images have display: none and when the image is clicked .show class is added for display.

when the cards are not matched , removed the .show class from the image.

but when I flip the second card it does not display the card, remove .show cards.

How do I delay the execution on next lines of code.

 let allCards=document.querySelectorAll('.card');

console.log(allCards);

for(let i=0;i<allCards.length;i++){
    allCards[i].addEventListener('click',flipOpen);
}

let flag=false;
let firstCard, secondCard;

function flipOpen(){
    
    this.firstElementChild.setAttribute('class','show');
    if(!flag){
        firstCard=this.firstElementChild;
        console.log("first card fliped");
        flag=true;
        return;
    }else{
        secondCard=this.firstElementChild;
        console.log("second card fliped");
        flag=false;
    }
    matchCards();
    
}

function matchCards(){
    if(firstCard.getAttribute('src')===secondCard.getAttribute('src'))
    {
        console.log("matched");

    }else{
       
        console.log('not matched');
        firstCard.classList.remove('show');
        secondCard.classList.remove('show'); 
    }
}

I’m still learning and I don’t know if this could help you, but you can try setInterval function, it takes two arguments, the first is a function and the second is the delaying time you want by millisecond .

setInterval(() => {},1000)

Keep in mind if you’re working with react that you need to clear this function by the clearInterval method, in vanilla JS I don’t think it’s a problem.

1 Like

I would actually recommend setTimeout instead of setInterval unless you want to repeat the same functionality over and over every x number of milliseconds.

@sukhanpreet356 Can you show us your full code (html, css, and JS)?

1 Like
<body>
    <div class="container">
      <header>
        <h1>Memory Game</h1>
      </header>
      <main>
        <section id="game-area">
          <div class="card">
            <img src="img/apple.jpg" alt="" />
          </div>
          <div class="card"><img src="img/cherry.jpg" alt="" /></div>
          <div class="card"><img src="img/apple.jpg" alt="" /></div>
          <div class="card"><img src="img/melon.jpg" alt="" /></div>
          <div class="card"><img src="img/melon.jpg" alt="" /></div>
          <div class="card"><img src="img/cherry.jpg" alt="" /></div>
        </section>
      </main>
    </div>
  </body>

CSS:

* {
    box-sizing: border-box;
    padding: 0%;
    margin: 0%;
}

body {
    display: flex;
    justify-content: center;
}

.container {
    width: 60%;
}

header {
    text-align: center;
    margin: 30px;
    font-size: 1.5rem;
}

#game-area {
    display: grid;
    grid-template-columns: 150px 150px 150px;
    grid-template-rows: 150px 150px;
    justify-content: center;
}

#game-area>div {
    border: 1px solid black;
    background-color: pink;
}

img {
    display: none;
    width: 100%;
    height: 100%;
}

.show {
    display: block;
}

JS

 let allCards=document.querySelectorAll('.card');

console.log(allCards);

for(let i=0;i<allCards.length;i++){
    allCards[i].addEventListener('click',flipOpen);
}

let flag=false;
let firstCard, secondCard;

function flipOpen(){
    if(this.firstElementChild.classList.contains('show')){
        console.log("already open ");
        return;
    }else if(!flag){
        this.firstElementChild.setAttribute('class','show');
        firstCard=this.firstElementChild;
        console.log("first card fliped");
        flag=true;
        return;
    }else if(flag){
        this.firstElementChild.setAttribute('class','show');
        secondCard=this.firstElementChild;
        console.log("second card fliped");
        flag=false;
    }
    matchCards();
    
}

function matchCards(){
    if(firstCard.getAttribute('src')===secondCard.getAttribute('src'))
    {
        console.log(firstCard.getAttribute('src'));
        console.log(secondCard.getAttribute('src'));
        console.log("matched");

    }else{
        console.log(firstCard.getAttribute('src'));
        console.log(secondCard.getAttribute('src'));
        console.log('not matched');
        disableCards();
    }
}

function disableCards(){
    setTimeout(()=>{
        firstCard.classList.remove('show');
        secondCard.classList.remove('show');
    },500); 

}

Just so I am clear, you are now satisfied with your current solution?

I used setTimeOut () .
So it solved my problem

Just wanted to make sure because it seemed like it was working as expected now.

Now you will need to figure out a way to prevent a user from clicking on a 3rd or 4th card before the setTimeout’s callback function runs.

Try clicking on one of the cards, then clicking on another non-matching card and then before the cards disappear clicking on one or two other cards. You will see the problem.

1 Like

yes, I see it.
should I decrease the time to solve this?

setTimeout(()=>{
        firstCard.classList.remove('show');
        secondCard.classList.remove('show');
    },500); 

No, that is not the solution. Someone could always find a way to click before the cards are hidden.

I used another Boolean variable to stop from clicking third card.

function flipOpen(){
    if(!stop){
        if(this.classList.contains('flip')){
            console.log('already fliped');
        }
        else {
            if(!flag){
                this.classList.add('flip');
                firstCard=this;
                flag=true; 
            }
            else{
                this.classList.add('flip');
                secondCard=this;
                flag=false;
                matchCards();
            }
        }
        
    }
    else{
        console.log('third-card');
    }
}

function matchCards(){
    stop= true;
    if(firstCard.dataset.card===secondCard.dataset.card){
        console.log('matched');
        score+=10;
        countScore();
        stop=false;
    } else{
        console.log('not matched');
        setTimeout(() => {
            firstCard.classList.remove('flip');
            secondCard.classList.remove('flip');
            countScore();
            stop=false;
        }, 1000);
    }
}