3.8.4 scheduleOnce 的问题

我需要一个随机间隔的定时器,于是写了下面一段代码:

let cb = () =>
{
    let randInterval = Math.random() * .1 + .1;
    console.log("scheduleOnce: randInterval=", randInterval)
    this.scheduleOnce(cb, randInterval);
}
cb();

这个定时器只会被调度一次,第二次只是更新了时间间隔,然后再也不会触发了,控制台输出如下:

按照注释所说: 如果回调任务已调度,那么将不会重复调度它,只会更新时间间隔参数
在这个一次性定时器的回调里面,其实任务属于即将消亡状态,它不能算已经调度的任务,因此更新时间间隔没有任何意义,因为后面紧接着就会把这个调度给杀了。

相反,这里如果使用 setTimeout 函数,则效果达到了预期。

let cb = () =>
    {
        
        let randInterval = Math.random() * .1 + .1;
        console.log("scheduleOnce: randInterval=", randInterval)
        const cb1 = () => {
            cb();
        }
        this.scheduleOnce(cb1, randInterval);
    }

    cb();

试试这样

感谢回复。这是通过改变cb值,让调度系统认为这是一个全新的调度,能解决问题,但是代码并不优雅。
希望引擎组认为这是一个问题并解决之。

let cb = () =>
    {
        
        let randInterval = Math.random() * .1 + .1;
        console.log("scheduleOnce: randInterval=", randInterval)
        this.scheduleOnce(() => cb(), randInterval);
    }
cb();

不优雅就让它变的优雅

1赞

老兄有点东西

:100: :+1:

应该是回调执行完,引擎才认为这个调度结束了。手动取消调度也可以的。
let cb = () => {

        let randInterval = Math.random() * .1 + .1;

        console.log("scheduleOnce: randInterval=", randInterval)

        this.unschedule(cb)

        this.scheduleOnce(cb, randInterval);

    }

    cb();

解决这个问题的方法有很多种,这不是重点,重点是目前的引擎行为不合理。 更新一个即将死亡的调度,此更新有何意义呢?

可能引擎认为一次性定时器,真的就只能执行一次,在这个回调执行完成之前,不能再次设置为定时器回调,也不存在合不合理的说法,它的好处就是很明显的避免了滥用定时器导致的意外情况

不大赞同这个观点。

  1. 如果连续调用2次,第二次发现存在,更新时间,这是没问题的,因为最终这个回调会执行一次。
  2. 即将触发回调的时候,因为是一次性定时器,系统是知道,该回调结束后,定时器就会消失,因此,它是一个即将死亡状态。回调里面再次调度,对一个即将死亡的定时器去更新间隔,是没有意义的,因为更新后,它也不会触发。这里就算直接报错,告知开发者设置了一个无法触发的定时器,都比现在的情况要好。定时器更新了,但不会触发,就是一个隐形的陷阱。
  3. 回调里面根据情况,再次定时触发该回调,是一种合理需求,并非滥用定时器。

是的,你可以花一两个小时研究一下源码hack一下,好修的,我之前修过。

重新调用前取消的做法是对的。scheduleOnce 第二次调用触发了重复调用检测。说明调用完毕后,引擎记录了此次调用,没有删除。
说白了,引擎的方法也没毛病,方法的意思就是【同一个方法只调用一次】,名字和 setTimeout 本来就不一样。前者强调的是方法,后者强调的是时间。设计上思路看过去就是不一样
你所要做的,就是调用前 unschedule。

最后补充一句,是你理解的 scheduleOnce 和 setTimeout 一致,引擎 API 可没这么说。了解 API 特性,顺应它,你会更顺畅。不要硬刚。

1赞

这个想修改很容易,触发一次性回调之前,先把记录清理掉就行。

您想要触发多次用 schedule不就行了。个人感觉您这样的代码可以优化下。。。

  1. 不存在硬刚。
  2. 我只是对这个现象说说自己的想法。论坛就是一个提想法、建议、问题的地方,这个是论坛存在的意义。
  3. 想法并不代表别人一定接受,也不能要求别人一定接受,但是可以提对不对。就好比每年人大提议一样,一些提议通过了,一些不通过,这是正常的事情,没有绝对对与错,只是一个选择。

schedule也可以,因为需要不定间隔定时器,每次在回调里面重新schedule以更新间隔,是一种方案哦。

嗯 多次的话还是这个schedule比较合适。once的话你这样用也没错,但是这样的代码可维护行不太好

这种写法却是可以的

当然可以,bind 每次生成一个新函数

1赞

修了就不能用引擎插件了