动态修改Javascript setInterval函数中的速度

动态修改Javascript setInterval函数中的速度,javascript,reactjs,Javascript,Reactjs,我有一个react应用程序,它需要以不同的句子间隔显示一些文本,一次显示一个 我所做的就是把所有的句子放在一个数组中,然后创建一个setInterval函数: startShowingText() { let i = 0 this.setState({ timer: window.setInterval(() => { this.setState({ sentence: SENTENCES[i] })

我有一个react应用程序,它需要以不同的句子间隔显示一些文本,一次显示一个

我所做的就是把所有的句子放在一个数组中,然后创建一个setInterval函数:

  startShowingText() {
    let i = 0

    this.setState({
      timer: window.setInterval(() => {
        this.setState({
          sentence: SENTENCES[i]
        })

        i += 1
      }, this.state.startingDuration)
    })
  }
不幸的是,这种方法有许多缺点:

1) 它需要一张支票才能终止

2) 我不能动态地修改时间,所以一旦设置了
this.state.startingDuration
,这将是所有句子的速度

3) 由于某些原因,如果我将
window.setInterval
函数指定给状态之外的变量,则不会执行该代码:

  startShowingText() {
    let i = 0
    console.log('here')
    const timer = window.setInterval(() => {
      this.setState({
        sentence: SENTENCES[i]
      })

      i += 1
    }, this.state.startingDuration)
    console.log('there')
  }
此代码正在打印:

这里

那里

不触发实际计时器


如何改进代码并使间隔可动态调整?

您可以使用从游戏开发世界借用的一种方法,在游戏开发世界中,他们创建以特定间隔运行的“游戏循环”。在循环中,您可以根据当前循环迭代确定是否是输出句子的时间

一个粗略的例子:

const语句={
“我的第一句话。”:1,
“我的第二句话。”:20,
“我的第三句话。”:25,
“我的第四句话。”:40
};
常数ticks=100;
常数maxLoops=100;
常数i=设置间隔(写操作,滴答声);
设loopCounter=0;
函数writeLoop(){
如果(loopCounter>maxLoops){
间隔时间(i);
}
for(句子中的句子){
让targetLoop=句子[句子];
if(loopCounter==targetLoop){
文件。书写(“”+句子+“”);
}
}
loopCounter=loopCounter+1;

}
您可以使用
设置超时
和递归函数,如下所示

类应用程序扩展了React.Component{
句子=[“第1句”、“第2句”、“第3句];
延迟时间=[10005003000];
建造师(道具){
超级(道具);
此.state={
已选择:0,
}
}
componentDidMount(){
这个。show句子();
}
show句子(){
const{selected}=this.state;
设置超时(()=>{
这个.setState({selected:(selected+1)%3});
这个。show句子();
},此.delayTime[所选])
}
render(){
返回(
{this.states[this.state.selected]}
);
}
}
ReactDOM.render(,document.getElementById('app'))

您可以递归调用
设置超时
并根据当前对话框更新速度

每个对话框的
速度是每秒键入的字母数

var对话框=[{
正文:“知识产权是一种权利,是一种权利,是一种权利,是一种权利,是一种权利。”,
速度:120
}, {
正文:“我们必须尽可能少地进行实验,以确保我们的实验室能够满足我们的需求。”,
速度:60
}, {
课文:“两人或两人在婚姻中的相互尊重是不平等的。”,
速度:90
}, {
正文:“不可因疏忽大意而导致死亡的例外情况,不得因疏忽而导致动物死亡。”,
速度:30
}];
让estimatedTime=dialog.reduce((d,e)=>d+((1000/e.speed)*e.text.length)/1000,0);
log(`estimatedTime:${estimatedTime.toFixed(3)}秒`);
var startTime=new Date().getTime();
typeDialog(dialog,document.getElementById('lorem'),()=>{
让endTime=newdate().getTime();
让持续时间=(endTime-startTime)/1000;
让延迟=持续时间-估计时间;
log(`Task take:${duration.toFixed(3)}秒`);
log(`Latency:${Latency.toFixed(3)}秒`);
});
函数类型对话框(对话框、目标、完成){
如果(dialog.length>0){
让索引=0,速度=1000/对话框[index]。速度,
Current段落=document.createElement('p');
targetEl.appendChild(当前段落);
类型字符(索引,0,速度);
函数类型字符(索引、字母、速度){
如果(字母>对话框[索引].text.length){
索引++;字母=0;
如果(索引<对话框长度){
速度=1000/对话框[索引]。速度;
Current段落=document.createElement('p');
targetEl.appendChild(当前段落);
}
}
如果(索引<对话框长度){
设置超时(()=>{
Current段落.textContent+=对话框[索引].text.charAt(字母);
字体字符(索引,字母+1,速度)
},速度);
}否则{
if(completeFn!=null){
completeFn.call();
}
}
}
}
}
。作为控制台包装。作为控制台行代码,
.作为控制台包装。作为控制台行::之后,
#洛雷姆p{
字体大小:较小;
}

最好使用
setTimeout
解决您的问题。您必须递归调用
setTimeout