Home > front end >  Run setTimeout with changing time values
Run setTimeout with changing time values

Time:05-06

I have an array of objects containing a field duration that specifies the duration that the Object should stay visible.

Each Object of array has it's own duration.

So i want to make each object appear after another with the help of setTimout.

Something like this : (onClick)

const playScenes = () => {
    const cpScenes = [...scenes];
    for(let i; i < cpScenes.length;i  ){
      const timer = setTimeout(() => {     
      showScene(cpScenes[i]);                 //Show the current scene
      }, cpScenes[i].duration);              //Time changes automatically
    }
    clearTimeout(timer);
  };

The way am thinking about this is that setTimeout should block execution of for loop and then run after specified time and then the loop continues..

CodePudding user response:

I don't really see how it is related to react, anyway, you can use recursion instead of for-loop to make it work

function playScenes(scenes) {
  if (scenes.length === 0) {
    return;
  }

  const [scene, ...rest] = scenes;
  setTimeout(() => {
    showScene(scene);
    playScenes(rest);
  }, scene.duration);
}

CodePudding user response:

Here's a simple for loop based solution:

function newComputerMessage() {
    let total = 0;
    for (let i = 0; i < cpScenes.length; i  ) {
        total  = cpScenes[i].duration;
        setTimeout(() => showScene(cpScenes[i]), total);
    }
}

In case you want to see the working, here's a working example snippet with dummy values:

let cpScenes = [5000, 5000, 3000, 4000]

function test() {
  let total = 0;
  for (let i = 0; i < cpScenes.length; i  ) {
    total  = cpScenes[i];
    setTimeout(() => showScene('test'), total);
  }
}

function showScene(num) {
  console.log(num);
}

test()

CodePudding user response:

Neither setTimeout nor setInterval block execution. Instead what you can do is wrapping it a promise like:

async function playscenes() {
   const cpScenes = [...scenes];
   for(let i; i < cpScenes.length;i  ){
      await (new Promise( (resolve) =>
         const timer = setTimeout(() => {
             showScene(cpScenes[i]);
             clearTimeout(timer);
             resolve();
         }, cpScenes[i].duration);
    })
}

Basically what this does, is for every single loop, the program will wait for the new Promise to resolve, which that happens when the timer has run out. If you don't understand asynchronous code (async/await) and promises work, I'd highly recommend that you do your research first. Although this code should not run inside an a React component since i assume that you change the state every time the setTimeout is triggered. What you could do is:

imports ...
async function playscenes(showScene){...}
let scenesPlaying = false;
export function YourComponent(...){
  ...
  if(!scenesPlaying) {
     playscenes(showScene);
     scenesPlaying = true;
  }
  ...
}
  • Related