探秘JS的异步单线程

探秘JS的异步单线程

对于通常的developer(特别是那些具备并行计算/多线程背景知识的developer)来讲,js的异步处理着实称得上诡异。而这个诡异从结果上讲,是由js的”单线程“这个特性所导致的。

我曾尝试用”先定义后展开“的教科书方式去讲解这一块的内容,但发现极其痛苦。因为要理清楚这个东西背后的细节,并将其泛化、以更高的视角来看问题,着实涉及非常多的基础知识。等到我把这些知识讲清楚、讲完,无异于逼迫读者抱着操作系统、计算机网络这样的催眠书看上好个几章节,着实沉闷而乏味。

并且更关键的是,在走到那一步的时候,读者的精力早已消耗殆尽,完全没有心力再去关心这个最开始的问题——js的异步处理为何诡异。

所以,我决定反过来,让我们像一个初学者那样,从一无所知开始,

先使用”错误的理念“去开始我们的讨论,然后用代码去发现和理念相违背的地方。

再做出一些修正,再考察一些例子,想想是否还有不大满意和清楚的地方,再调整。如此往复,我们会像侦探那样,先从一个不大正确的假设开始,不断寻找证据,不断修正假设,一步步追寻下去,直到抵达最后完整的真相。

我想,这样的写作方式,更符合一个人真正的求知和研究过程,并能够为你带来更多关于”探索问题“的启发。我想,这样的思维方式和研究理念,比普通的知识更为重要。它能够让你成为知识的猎人,有能力独立地觅食,而不必被迫成为婴孩,只能坐等他人喂食。

好了,让我们先从一块js代码,开始我们的探索之旅。

console.log('No. 1');

setTimeout(function(){
    console.log('setTimeout callback');
}, 5000);

console.log('No. 2');

输出结果是:

No. 1
No. 2
setTimeout callback

多次运行后,发现依旧无法改变。这其实是有点奇怪了。因为通常的并行计算、多线程编程中,通过多次运行,你其实是可以看到各种无法预期的结果的。在这里,竟然神奇地得到了相同的执行顺序结果。这就反常了。

但我们还无法完全下一个肯定的结论,可不可能因为是setTimeout的启动时间太长,而导致”No. 2“这条语句先被执行呢?为了做进一步的验证,我们可以在”No. 2“这条打印语句之前,加上一个for循环,给setTimeout充分的时间去启动。

console.log('No. 1');

setTimeout(function(){
    console.log('setTimeout callback');
}, 0);

for (let i = 0; i < 10e8; i++) {}

console.log('No. 2');

运行这段代码,我们发现,”No. 1″这条打印语句很快地显示到了浏览器命令行,等了一秒钟左右,接着输出了

No. 2
setTimeout callback

 

 

 

发表评论