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;
}
...
}