JavaScript之setTimeout
JavaScript之setTimeout
由setTimeout引发的一些了解 -> 事件循环机制、异步队列、时钟周期、执行上下文
js里常见的2个定时器:
setTimeout和setInterval,指定一定时间后触发其第一个参数函数(异步回调函数)然后执行函数体内的代码发生一些操作、变化….
e.g.1
1  | setTimeout(function(){console.log(4)},0);  | 
Pormise,
Promise对象代表一个异步操作,它有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败),Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。
先看
1  | setTimeout(function () {  | 
在浏览器控制台可以看到好像确实是立马就输出123了。
先看下
1  | for (var i = 0; i < 1000; i++) {  | 
这个很好理解,常规思维都是顺序执行,这个结果也是如常规思维所想。
再看(改变下顺序):
1  | setTimeout(function () {  | 
在浏览器控制台执行,发现先输出的是for循环内的内容,无论循环条件里是1000还是100 或是 10,都是先执行的循环体最后执行的setTimeout
分析:首先代码被JS解释引擎(如V8)顺序加载解释并执行,到遇到setTimeout函数时,会将其第一个function参数函数放入异步队列排队等待线程空闲后再按照队列顺序执行。
new Promise是第一个参数是一个同步函数,new Promise 最终返回的结果是一个promise对象, .then()方法也是异步的,所以代码执行到此处时会将.then()的回调函数放入一个异步队列,当new Promise返回的promise达到fulfilled状态时且当前线程空闲时就会执行.then()内的异步回调函数输出结果5, 再接着执行console.log(3); 控制台输出3。
最后当前JS线程已将代码遍历完并执行完,然后获取异步队列的内回调函数,这里关键在于:为什么先执行的是new Promise返回的Promise对象的.then()里的方法而不是setTimeout里的参数函数。因为浏览器或webview的时间钟,时间钟是由机器硬件的时间周期决定(CPU时钟周期)。
总结:js主线程在执行当前代码这个线程手里,当前线程只有空闲后,才回去处理事件队列,虽然setTimeout 设定的时间已到,但是也得等队列里所有代码已执行完毕,最后才处理setTimeout里的东西。
1  | setTimeout("console.log('test!')", 1000);  | 
执行试试。必须要等待用户点击确认按钮后才会继续执行。
因为alert挂起了主线程,使得当前主线程被block(同样的函数还是prompt(), confirm()),主线程被挂起,整个当前执行js的进程进入等待状态,事件触发或代码执行都被中断,计时器也会暂停计时 ,当主线程恢复后,余下的代码继续执行,计时器安装时钟周期重新开始计时。
再看外国网站的例子[JakeArchibald.com]
e.g.2
1  | console.log('script start');  | 
运行输出:
1  | script start  | 
Promise对象经过resolve后的.then是异步的. 所以promise1 和 promise2的输出会在第3、4行输出;(setTimtout是因为 异步队列+系统时钟周期导致最后被执行–即当前线程空闲时)
进一步修改示例
e.g.3
1  | console.log('script start');  | 
运行后输出:
1  | script start  | 
再修改:
e.g.4
1  | console.log('script start');  | 
1  | #输出:  | 
这是因为
new Promise()里接受一个函数参数function(resolve,reject)用来执行异步执行成功或失败后的处理逻辑。
1  | let promise = new Promise(function(resolve, reject){  | 
new Promise()里的参数函数,在代码被执行到此处时可以认为是同步执行的,其返回的Promise对象使用.then链式调用时其内的函数是被异步执行。
参考:
https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
https://github.com/abbshr/abbshr.github.io/issues/32
http://www.jianshu.com/p/063f7e490e9a [Promise基础]
    
        
        版权声明:
        本文由Lomo创作和发表,采用署名(BY)-非商业性使用(NC)-相同方式共享(SA)国际许可协议进行许可,
        转载请注明作者及出处,本文作者为Lomo,本文标题为JavaScript之setTimeout.
    
    
 
