Javascript的单线程和异步之间的关系
本文介绍javascript的异步和单线程的关系,以及简单解释了单线程的js怎么异步处理。
异步计时函数setTimeout()
1 | var begin = new Date();//代码开始 |
上面的代码跟下面的对比一下:
1 | var begin = new Date();//代码开始 |
解析:
当js解析器解析到setTimeout时,就调用了浏览器的api——异步函数setTimeout,此时js继续往下解析执行,而浏览器就另有一个线程来处理异步函数setTimeout,也就是1秒后把回调函数放入js执行队列中。而此时,js调用栈中继续执行剩下的代码,直至完成了后面的循环后(调用栈中所有代码已经执行完毕)才解析队列中的回调函数来执行。
异步IO函数
这里我们介绍下ajax,为了方便起见,直接使用jquery来说明
1 | $.get('http://blog.zjien.com', function(resData){ |
js在解析并执行到$.get()时,发起http请求,我看打开F12可以看到请求是处于Pending状态,通过WireShark或Fiddler2可以查看到HTTP请求状态,可知请求是成功发送并且有响应,但是因为下面的while是死循环,因此$.get()里的回调函数一直在队列中排队,得不到js的解析和执行,呈现出假死的状态。
换一种形式来展示
1 | $.get('http://blog.zjien.com',function(resData){ |
js解析并执行到go on时,浏览器弹出窗口,暂时不要关闭窗口,通过F12可以看到,请求是Pending状态,但通过Wireshark等工具看到请求是完成并得到响应的,只是因为go on阻塞/阻止了时间循环,导致$.get的回调无法执行,只有按下确定关闭了go on框,回调才得以执行。这是在chrome的情况如此。
在Firefox下却不会出现此情况,go on并不能阻止事件循环,所以上面两个代码段的ajax($.get)的回调都可以执行,于是界面出现3个alert弹框。
注意,每个窗口有一个js线程(单线程),若一个窗口中有多个tag,那么这多个tag都是用同一个js线程。