简体   繁体   English

如何让循环等待事件监听器?

[英]How to make a loop wait for an event listener?

I am trying to create a coin toss game where you set the number of games you want to play, and then choose head or tails for each iteration.我正在尝试创建一个抛硬币游戏,您可以在其中设置要玩的游戏数量,然后为每次迭代选择正面或反面。 But my for loop doesen't wait for the eventListener and the loop is over before the user even clicked once.但是我for循环不会等待 eventListener,并且在用户单击一次之前循环就结束了。

function play(){
    head.addEventListener("click", choice);
    tails.addEventListener("click", choice);
}
function choice(e){
    let random = Math.floor(Math.random() *2);
    console.log(random);
    let clicked = e.target;
    e.target.style.border = "3px solid green";
    head.removeEventListener("click", choice);
    tails.removeEventListener("click", choice);
    if (random == 0){
        result.src = head.src;
        result.style.height = "100%";
        if(result.src == clicked.src){
            result.style.border = "3px solid green";
            
        }
        else{
            result.style.border = "3px solid red";
            
        }
    }
    if (random == 1){
        result.src = tails.src;
        result.style.height = "100%";
        if(result.src == clicked.src){
            result.style.border = "3px solid green";
            
        }
        else{
            result.style.border = "3px solid red";
            
        }
    }
    setTimeout(refresh, 3000);
    function refresh(){
        result.style.border = "none";
        clicked.style.border = "none";
    }

}

function wait(){
for (let i = 0; i < playAmount; i++){
    console.log(i);
    play();
}
}
wait();

Thank you in advance!先感谢您!

You can solve this problem without for loop.你可以不用 for 循环来解决这个问题。 Just take a variable count = 0 and flag = false at the starting.只需在开始时使用变量 count = 0 和 flag = false 。 Now just follow the program as under现在只需按照下面的程序进行操作

var count = 0 , flag = true ;
    flag&&head.addEventListener("click", choice);
    flag&&tails.addEventListener("click", choice);
function choice(e){
    if(count>=playAmount)flag=false;
    else count++;
    let random = Math.floor(Math.random() *2);
    console.log(random);
    let clicked = e.target;
    e.target.style.border = "3px solid green";
    head.removeEventListener("click", choice);
    tails.removeEventListener("click", choice);
    if (random == 0){
        result.src = head.src;
        result.style.height = "100%";
        if(result.src == clicked.src){
            result.style.border = "3px solid green";
            
        }
        else{
            result.style.border = "3px solid red";
            
        }
    }
    if (random == 1){
        result.src = tails.src;
        result.style.height = "100%";
        if(result.src == clicked.src){
            result.style.border = "3px solid green";
            
        }
        else{
            result.style.border = "3px solid red";
            
        }
    }
    setTimeout(refresh, 3000);
    function refresh(){
        result.style.border = "none";
        clicked.style.border = "none";
    }

}

I hope this solves your problem.我希望这能解决你的问题。

Let us go through some key parts of your implementation(refer to my comments inline)让我们 go 通过您实施的一些关键部分(参考我的内联评论)

function play() { 
  head.addEventListener("click", choice);
  tails.addEventListener("click", choice);
  
  //the above 2 lines add a click event listener to the two buttons,
  //that is, whenever these 2 buttons are clicked,
  //the function `choice` will be called
}
function choice(e) {
  let random = Math.floor(Math.random() * 2);
  console.log(random);
  let clicked = e.target;
  e.target.style.border = "3px solid green";
  head.removeEventListener("click", choice);
  tails.removeEventListener("click", choice);
  
  //the above 2 lines remove the click event listener from the two buttons
  //that is, now the function `choice` will not be called at button click 
  
  if (random == 0) {
    result.src = head.src;
    result.style.height = "100%";
    if (result.src == clicked.src) {
      result.style.border = "3px solid green";
    } else {
      result.style.border = "3px solid red";
    }
  }
  if (random == 1) {
    result.src = tails.src;
    result.style.height = "100%";
    if (result.src == clicked.src) {
      result.style.border = "3px solid green";
    } else {
      result.style.border = "3px solid red";
    }
  }
  setTimeout(refresh, 3000);
  function refresh() {
    result.style.border = "none";
    clicked.style.border = "none";
  }
}

function wait() {
  for (let i = 0; i < playAmount; i++) {
    console.log(i);
    play();
    //calls the play function `playAmount` times
  }
}
wait();

Now let us discuss the problems with this approach现在让我们讨论一下这种方法的问题

  1. Calling the play() function playAmount times from wait() (tries to) binds(adds) the click event listener to both the buttons playAmount times, but adding the same function n times as an event listener is same as adding it once, reference: addEventListener docswait()调用play() function playAmount次(尝试)将点击事件侦听器绑定(添加)到两个按钮playAmount次,但是添加相同的 function n次作为事件侦听器与添加一次相同,参考: addEventListener 文档
  2. once choice is called, you remove the event listeners from both the buttons (remember, the event listeners were only bound once in a loop in the wait() function), now with no event listener bound on the buttons, the buttons wont register the event click anymore.一旦choice被调用,你从两个按钮中删除事件监听器(记住,事件监听器只在wait()函数的循环中绑定一次),现在按钮上没有绑定事件监听器,按钮不会注册事件点击了。

The below implementation should work for you:下面的实现应该适合你:

let numberOfTurnsTaken = 0;
//add a global variable to count the turns taken

function play() { 
  head.addEventListener("click", choice);
  tails.addEventListener("click", choice);
  //bind the event listeners
}
function choice(e) {
  numberOfTurnsTaken++;
  //increment the turns
  let random = Math.floor(Math.random() * 2);
  console.log(random);
  let clicked = e.target;
  e.target.style.border = "3px solid green";

  //remove the event listeners only when the turns are over and we are `handling` the last turn
  if(numberOfTurnsTaken == playAmount){
    head.removeEventListener("click", choice);
    tails.removeEventListener("click", choice);
  }
  
  if (random == 0) {
    result.src = head.src;
    result.style.height = "100%";
    if (result.src == clicked.src) {
      result.style.border = "3px solid green";
    } else {
      result.style.border = "3px solid red";
    }
  }
  if (random == 1) {
    result.src = tails.src;
    result.style.height = "100%";
    if (result.src == clicked.src) {
      result.style.border = "3px solid green";
    } else {
      result.style.border = "3px solid red";
    }
  }
  setTimeout(refresh, 3000);
  function refresh() {
    result.style.border = "none";
    clicked.style.border = "none";
  }
}

//set things rolling by binding click event handlers on the buttons
play();


//the loop is no longer needed
//function wait() {
//  for (let i = 0; i < playAmount; i++) {
//    console.log(i);
//    play();
//  }
//}
//wait();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM