之前对JS的同步和异步一直搞不清楚,今天看了些文章,谈谈自己的理解。
异步函数往往是有等待性质的函数,主流程在执行到等待的时候,为了提高效率,就把这个函数挂起了,放进一个等待的队列。接着主程序继续执行后面的函数。
一直执行到主程序队列里的函数执行完毕,这时主程序再去查询等待队列里哪个程序等待结束。这个查询发生的条件是主程序里的函数都执行结束。如果等待队列里有已经结束等待的函数,主程序就把它拿到主程序队列里执行并返回结果。
就像一个坐诊医生,病人A,B,C,D依次来看病。
A进入诊室,B,C,D在后面排队等待。
A的病很简单,医生检查开药,诊断结束。
A离开诊室,B进入诊室,C,D在后面排队。
B的病情复杂,医生说你去查个血,等我看完后面的病人再来找你。
B离开诊室,C进入诊室看病,D在后面排队;
C看完后,离开诊室,D进入诊室。*不论此时B是否已经查血完成
D看完后离开。如果没有新的病人来,这时医生每隔一段时间查看B的查血报告是否完成。
如果发现B的查血报告,就叫B进入诊室,继续诊断开药,诊断结束。
值得注意的是,B有个简单的初诊(执行到挂起阶段),在B离开后(进入等待队列),哪怕B的查血报告很快出来,也需要等到D结束诊断后才能继续进行诊断。
用程序模拟如下:
(function f() {
console.log('开始看病');
console.log('A看病结束');
setTimeout(()=>console.log('B看病结束'),0);
console.log('C看病结束');
console.log('D看病结束');
})();
运行结果为:
可见B只用了0毫秒去查血,仍要等所有人都结束后才能继续看病
之前很疑惑异步函数是否不做任何处理直接放到挂起等待的队列,等所有程序都结束才开始执行异步函数。
用以下程序验证发现,异步函数在进入等待挂起前开始倒计时,只是倒计时结束不会返回结果。
(function f() {
console.log('begin function.');
setTimeout(()=>console.log(1),1000);
setTimeout(()=>console.log(2),2000);
setTimeout(()=>console.log(3),6000);
var start_t=new Date().getTime();
while(new Date().getTime()-start_t<5000){}
console.log('end function!');
})();
结果中会先输出'end function!',然后很快依次输出1,2,等待大约1秒输出3