运行 setTimeout 改变时间值

Run setTimeout with changing time values

我有一个包含字段 duration 的对象数组,该字段指定 Object 应保持可见的持续时间。

数组的每个 Object 都有自己的 duration

所以我想在 setTimout 的帮助下让每个对象一个接一个地出现。

类似这样的事情:(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);
  };

我的想法是 setTimeout 应该阻止执行 for 循环,然后在指定时间后 运行 然后循环继续..

setTimeout 和 setInterval 都没有阻止执行。相反,您可以做的是将其包装成一个承诺,例如:

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

基本上,对于每个循环,程序将等待 new Promise 解决,这发生在计时器 运行 结束时。 如果您不了解异步代码 (async/await) 并且 promises 工作,我强烈建议您先进行研究。 尽管此代码不应 运行 在 React 组件内,因为我假设您每次触发 setTimeout 时都会更改状态。 你可以做的是:

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

我真的不明白它与 react 有何关系,无论如何,您可以使用 recursion 而不是 for-loop 来使其工作

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

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

这是一个简单的 for 基于循环的解决方案:

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

如果您想查看工作情况,这里有一个带有虚拟值的工作示例片段:

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()