JavaScript中setTimeout函数工作机制及页面跳转回调执行问题
嘿,这个问题挺接地气的,我来一步步给你掰扯清楚~
首先得明确:JavaScript是单线程的,所有代码都得排队在调用栈里执行。setTimeout的本质是把回调函数“推迟”到指定时间后,放到宏任务队列里等待执行,而不是立刻触发。
哪怕你写setTimeout(fn, 0),它也不会马上跑——因为得等当前调用栈里的所有同步代码都执行完,同时当前轮次的微任务队列也处理干净,才会轮到宏任务队列里的这个回调。说白了,setTimeout(fn, 0)就是把任务塞到下一轮事件循环里执行。
答案是:大概率会被中断,甚至完全不执行。
当你点击绑定了onclick的元素时,浏览器会先执行onclick里的同步代码。如果代码里有跳转操作(比如window.location.href = '新页面地址'),这是个同步的浏览器操作——浏览器会立刻开始卸载当前页面的资源、销毁当前的JavaScript执行环境。
这时候如果你的回调是同步代码,可能刚执行到一半,页面就开始卸载了,自然会被中断;如果是异步回调,还没等到它进入任务队列,页面环境已经没了,根本没机会执行。你测试到的“中途被中断”,就是这个原因。
结果依然不太乐观——这个回调几乎还是不会执行。
把回调用setTimeout(fn, 0)包裹后,回调会被放到宏任务队列里。但跳转操作是同步的,会在当前调用栈的所有代码执行完后,立刻触发页面卸载。而宏任务队列里的回调要等下一轮事件循环才会被取出执行,但此时页面已经开始销毁了,浏览器会直接终止当前页面的所有待执行任务,所以这个回调根本没机会跑起来。
除非你把跳转操作也改成异步的(比如用setTimeout包裹跳转),那原回调才有机会在跳转前执行,但如果是同步跳转,哪怕包了0延迟的setTimeout,也救不了它。
内容的提问来源于stack exchange,提问作者user2608008

