Yash Munjal
Yash Munjal

Reputation: 31

How to have a specific function break free from the setInterval loop>

I have the following code with a setInterval() method. However there is one function in between i.e audio.play(). Whenever setInterval is called the whole function is called again and so the audio plays again and again. Is there any way of run the setInterval() method but have an exception for the audio.play part? Here is the code

setInterval(async () => {
    //api stuff
    const detections = await faceapi
      .detectAllFaces(video, new faceapi.TinyFaceDetectorOptions());
    const resizedDetections = faceapi.resizeResults(detections, displaySize);
    const happy  =resizedDetections[0].expressions.happy;

    //The Issue  starts from here
    if(happy>0.9)
    {
      audio.src="audios/happy_audio.wav";
      audio.play();
    }

    faceapi.draw.drawDetections(canvas, resizedDetections);
    faceapi.draw.drawFaceExpressions(canvas, resizedDetections);
  },1000)
})

Upvotes: 1

Views: 139

Answers (3)

Alex - Tin Le
Alex - Tin Le

Reputation: 2000

I got it. So you want to stop the interval as soon as the happy index is > 0.9

let intervalID = setInterval(async () => {
    //api stuff
    const detections = await faceapi
      .detectAllFaces(video, new faceapi.TinyFaceDetectorOptions());
    const resizedDetections = faceapi.resizeResults(detections, displaySize);
    const happy  =resizedDetections[0].expressions.happy;

    //The Issue  starts from here
    if(!audio.paused && happy>0.9)
    {
      audio.src="audios/happy_audio.wav";
      audio.play();
      clearInterval(intervalID); // to stop next interval
      return; // to stop current interval
    }

    faceapi.draw.drawDetections(canvas, resizedDetections);
    faceapi.draw.drawFaceExpressions(canvas, resizedDetections);
  },1000)
})

Upvotes: 0

V. Sambor
V. Sambor

Reputation: 13409

As it was already said in comments, better is to move outside setInterval the code you want to run once.

But if you really want to keep it inside, then you can use a boolean variable which will allow to run only once.

Here is how:

let isFirstRun = true;

setInterval(async () => {
    //api stuff
    const detections = await faceapi
      .detectAllFaces(video, new faceapi.TinyFaceDetectorOptions());
    const resizedDetections = faceapi.resizeResults(detections, displaySize);
    const happy  =resizedDetections[0].expressions.happy;

    //The Issue  starts from here
    if(isFirstRun) {
        isFirstRun = false;

        if(happy>0.9)
        {
          audio.src="audios/happy_audio.wav";
          audio.play();
        }
    }
    faceapi.draw.drawDetections(canvas, resizedDetections);
    faceapi.draw.drawFaceExpressions(canvas, resizedDetections);
  },1000)
})

Upvotes: 0

zfrisch
zfrisch

Reputation: 8670

If you want it not to play while it is playing you could check and see if the audio is currently playing by checking the paused property in the conditional:

setInterval(async () => {
    //api stuff
    const detections = await faceapi
      .detectAllFaces(video, new faceapi.TinyFaceDetectorOptions());
    const resizedDetections = faceapi.resizeResults(detections, displaySize);
    const happy  =resizedDetections[0].expressions.happy;

    //The Issue  starts from here
    if(!audio.paused && happy>0.9)
    {
      audio.src="audios/happy_audio.wav";
      audio.play();
    }

    faceapi.draw.drawDetections(canvas, resizedDetections);
    faceapi.draw.drawFaceExpressions(canvas, resizedDetections);
  },1000)
})

if you just want it to fire once use a flag:

let flag = false;

setInterval(async () => {
    //api stuff
    const detections = await faceapi
      .detectAllFaces(video, new faceapi.TinyFaceDetectorOptions());
    const resizedDetections = faceapi.resizeResults(detections, displaySize);
    const happy  =resizedDetections[0].expressions.happy;

    //The Issue  starts from here
    if(flag && happy>0.9)
    {
      audio.src="audios/happy_audio.wav";
      audio.play();
      flag = true;
    }

    faceapi.draw.drawDetections(canvas, resizedDetections);
    faceapi.draw.drawFaceExpressions(canvas, resizedDetections);
  },1000)
})

Note I'm not a big fan of variable flags that are globally scoped. In the above case I would recommend a closure, or binding your asynchronous function to an Object that houses the flag, but as an example this should be sufficient :)

Upvotes: 1

Related Questions