在JavaScript中存在异步的概念:异步函数,用回调处理异步,用promise处理异步......
但千真万确的是,JavaScript是同步执行的、单线程的、一次只能做一件事情。
Synchronous and Asynchronous
首先看两个词,强烈建议:在观念里用它们取代“同步”和“异步”。
Synchronous:
one thing at a time
Asynchronous:
more than one thing at a thime
最初接触同步/异步概念的时候觉得非常奇怪,同步(synchronous)在中文中,是一起做,一个时间得做几个事情;异步(asynchronous)则反之。
但在这里中,它们的意思却恰好相反,Synchronous是一个时间点下只做一件事,Asychronous是一个时间点下做几件事情。
但如果看这两个单词,思路会清晰很多,syn是词根,代表“一”,跟some起源一样。
单线程的JavaScript通过回调处理处理异步

发生在一个浏览器中,一个时间点下发生的事情不只一个: JSE在一行一行读者JS代码;渲染引擎在绘制页面;Http模块在发送、接收数据...... 它们是在同时进行的。
浏览器在做多件事情,JSE只能做一件事情。并且,浏览器里的其他人,和JSE是有“交流”的。
他们可能会加塞给JSE一个新的任务,这就需要JSE能处理异步的能力。
JSE的处理方式是,开一个event queue。把所有来自浏览器内部,JSE外部的,需要被执行的任务,都放入event queue中。等执行栈空闲了,在从event queue里一个个读取,执行。
用这段代码来举例:
function waitThreeSeconds() { //函数被调用三秒之后打印finished function
var ms = 3000 + new Date().getTime();
while (new Date() < ms){}
console.log('finished function');
}
function clickHandler() {
console.log('click event!');
}
// listen for the click event
document.addEventListener('click', clickHandler);//点击屏幕后调用clickhandler,打印click event
waitThreeSeconds();
console.log('finished execution');
如果不点击屏幕,在三秒之后会先后打印:
finished function
finished execution
如果函数执行的三秒内点击屏幕:
finished function
finished execution
click event!
clickHandler被放到event queue中了,当所有写下的代码执行完,才会轮到它。这个clickHander是回调函数,当click这个异步事件发生了,执行栈空了,异步回调函数才开始被执行。