javascript - JS是基于什么考虑不提供当前所有正在执行的定时任务的句柄?

 

问题描述:

定时句柄会拿不到
为什么不出个getAllInterval,getAllTimeout之类的函数?
是因为安全问题, 性能问题还是别的原因不提供的?


 

第 1 个答案:

为什么?也许他们就是单纯地没想到

JS 中欠考虑的设计多了去了,所以很多问题你与其思考设计者为什么“考虑不”,不如在心中默认他们是“不考虑”。

题目里说的那种接口可能存在什么问题

在我看来,现有的setTimeout这种以简单类型作为任务标识的接口确实是有一定的隐患的,恶意开发者可以非常轻易地干预其他模块的延时任务,如果再定制一个更好使的接口出来,那无异于是给恶意代码递棍子(为什么不是递刀子呢?因为这个隐患其实不大,基本是安全的)。
JS 虽然没有提供这样的接口,但是据我的经验,主流浏览器里面浏览器定时器/延时器返回的都是递增的整数,所以我们可以通过枚举的方法来干预页面里的所有定时/延时任务
比如下面的代码就可以枚举取消浏览器中既有的全部延时任务,在一些使用延时器做动画或其他调度的页面上运行,可能会导致页面出 bug :

const MAX_HANDLER_ID = setTimeout(_=>_);
for(let i = 0; i <= MAX_HANDLER_ID; i++){
  clearTimeout(i);
}

下面这段代码则可以把 Bilibili 首页的轮播图暂停下来:

const MAX_HANDLER_ID = setInterval(_=>_);
for(let i = 0; i <= MAX_HANDLER_ID; i++){
  clearInterval(i);
}
?你看,因为接口是这样设计的,所以不用他们给我递棍子,我还是可以整点花活,只不过这只能算一个花活,没有任何危险。

不过制定规范的人显然对这种事情不以为意,不然后面出的 requestAnimationFrame 接口就应该返回 Symbol ,以防此类枚举。


 

第 2 个答案:

唉,这和什么JS不JS的无关吧?你用啥语言做个定时任务还有个句柄的?充其量你写这个定时啥的就是个函数。

举个很简单的例子,PHP中你要做延时就是加一个sleep(10)(延迟10秒),golang中暂停执行也是:time.Sleep,哪里还提供啥句柄给你,你自己处理的定时就自己想办法通过其他方式解决掉取消定时这个问题,根本就没有说给你个句柄做啥取消。

JS提供给你了,让你给方便取消啥的,你还想要个获取所有定时句柄的操作,另外你自行想一下,如果要提供给你所有句柄,让你去写这么一个getAllInterval或者getAllTimeout你怎么去实现?

所以如果你想,你自己写一个呗,再封装一层函数,类似于:

var allIntervalHandle = [];
function customSetInterval(callback,seconds) {
    var handle = setInterval(callback,seconds);   
    allIntervalHandle.push(handle)
}

function getAllInterval() {
    return allIntervalHandle;
}

 

第 3 个答案:

定时器不是会返回句柄/唯一标识吗, 你想实现这个功能可以自己做

const hwnd = setTimeout(()=>{}, 10000)
const hwnd = setInterval(()=>{}, 1000)

 

第 4 个答案:

JavaScript 不提供对当前所有正在执行的定时任务的句柄的主要原因是考虑到了灵活性和可用性。

JavaScript 中的定时任务主要是使用 setTimeout 和 setInterval 函数来实现的。这些函数可以方便地创建定时任务,但是不提供直接访问定时任务的句柄,使得它们不能直接控制和管理定时任务。这是为了保证定时任务的灵活性和可用性,以避免出现意外的结果,并确保代码的可维护性。

然而,如果需要在定时任务执行完毕后对其进行管理,可以使用返回的句柄,通过 clearTimeout 和 clearInterval 函数来清除定时任务。这样,就可以在任意时间内停止定时任务,并且不会影响其他正在执行的定时任务。


我的 doc 结构如下:{ "id":"sadhiuasdhuasi", "user_id":12, "content":"每个人都不得 ...