Appearance
定时器
元信息
- 目标:用 setTimeout/setInterval 建立"稍后执行"的异步体感——代码顺序≠执行顺序;观察 alert 等阻塞操作如何让定时器排队,理解 js 单线程下异步执行的不确定性
- 关键概念:定时器、系统事件、一次性/循环事件、异步执行、代码顺序与执行顺序、阻塞、单线程
- 关联阶段:cp3
- 常见误区:以为 setTimeout(fn, 3000) 保证 3 秒整执行(到点后还需等主线程空闲);以为代码写在后面就后执行(回调执行顺序与代码顺序无关);把"输出 12 还是 21"当浏览器 bug(异步系统执行顺序本就不确定)
什么是定时器?
定时器是一种系统事件,由运行环境实现和触发。
通过定时器,开发者可以不依赖于用户的操作而自动调用执行某些代码
js中支持两种定时器事件:一次性事件、循环事件
定时器示例
输出结果是:
"hello from console"
"hello from window"
异步执行
- 代码顺序:在代码中的前后顺序,反映了编辑时的两段代码之间的顺序。
- 执行顺序:在运行时的顺序。对于支持异步执行的系统,执行顺序是不确定的。
js定时器允许函数引用作为它的参数,使得函数的声明和执行分离为两个阶段。
- setTimeout(alertFunc, 3000)本身是函数声明和执行为一体的,它与后面的console.log("hello from console")是同步关系
- alertFunc则分为声明和调用两个部分。其中调用过程是隐式的, 它由系统来执行,调用时点则取决于定时器函数的设置。
也就是说alertFunc()的执行顺序与它所在的代码顺序无关,称之为异步执行。
被阻塞的定时器
- 当"我是窗口主线程"的对话框未被用户点击OK按钮之前,两个定时器均不会被执行(被阻塞),即使定时时间已超时。
- 假如用户先等足3秒之后,再点击对话框的OK按钮, 则两个定时器处理函数会立即被执行,似乎这些定时器已排队到位,但等待前面的代码被执行完毕。
- 进一步观察发现:
alert这一类涉及操作系统子窗口的函数被执行时,浏览器主窗口将无法接收用户的输入,其代码也停止执行;故这类包含窗口函数的代码是典型的阻塞式操作。也因此应当避免使用alert这类功能
异步执行:不确定的运行时顺序
上述结果是12还是21,取决于浏览器所在机器执行循环的实际时间
如果你希望确保输出的是12,该如何做? 在后续的ajax中,我们将再次讨论异步
同步与异步、串行与并行这两组词之间的区别?