讲故事,消惑蛊
首先,我们将 Js 代码看作是 A ,A 只有1个人(单线程),同一时间只能做一件事,这部分是阻塞的,一项工作执行完才能执行下一项,比如一个 for 循环:
// 我是一段孤独的循环
for( let t = 0 ; t < 10000 ; t++ ){
console.log(t);
}
只有第一次循环执行完才能执行第二次循环,第二次循环执行完才能执行第三次……所以 A 重复做了一万次工作(累死),假设每个工作要做1秒,那么 A 做完所有工作要花1万秒。 这就叫做阻塞
。
然后,我们假设NodeJS 是一个团队 Arr,那么我们就可以不让 A 自己去做,同一时间可以做多件事;
比如送信(IO)这种事情就可以委托给 Arr 来做, Arr 是一个团队,有无数个人随时等着接活。
某一天 A 想写两封信分别送给不同的人,于是他先写第一封信,花了1个小时时间,然后直接把这封信交给 Arr , Arr 派手下的人去送信,并承诺 A ,当送信的人回来的时候(事件),会告诉(回调) A 信是否送到了。这时候 A 可以等着 Arr 的消息,但是会闲的蛋疼,于是他决定不等,了直接写第二封信。过了半小时, Arr 送信的人回来了(事件触发),来到 A 门前敲 A 的们,此时 A 正在专注地写一段文字,听到敲门声,他说:“稍等一下(阻塞),这句马上写完。”等他写完了这一句(响应事件),就放下笔,去开门, Arr 的人告诉他(回调)信送到了, A 说了声谢谢就让对方回去了。然后 A 又继续拿起了笔写信,又过了半小时总算写完,又让 Arr 去送信…… Arr 送信的时候不会阻止(阻塞)A 做其他工作,这就是非阻塞。
A 第一封信写了1小时,第二封信也写了1小时, Arr 送第一封信用了半小时,送第二封信我们先不看; 也就是说从 A 开始写第一封信到写完第二封信,一共花了2小时时间,如果第一封信是 A 亲自去送,假设他来回也只花半小时,那么那么他第二封信写完就会比原来晚半小时。 刚才说 Arr 手下人很多,就算 A 提前写好了10封信,一封一封交给 Arr , Arr 也可以派10个人同时送这些信,假设最远的路途来回需要40分钟,那么 A 也可以在40分钟后知晓全部10封信的运送结果。 那如果是100封信、1000封信呢?知道所有信的运送结果的时间几乎等于送得最远的一封信的来回时间。
这就是为什么
Node单线程
还能适用于IO密集型应用
,一方面 Arr 足够强大能同时做多个跑腿工作,另一方面 Arr 和 A 之间约定了一个高效的合作流程(事件驱动的非阻塞回调)。
Node当中,fs.writeFile是把writeFile这件事委托给 Arr 去做了, Arr 执行这个工作的时候, A 可以做其他事情;而fs.writeFileSync虽然也是交给 Arr 去做,但 A 执意要等 Arr 回信儿了才肯做其他事情,等待的这段时间 A 是被阻塞的,没法做其他事情(所以你自己愿意等谁也没办法!)。
IF
你还不清楚,那么:
设
店A
采用同步
的方式: 客户1去餐厅点餐付款之后,要等客户1餐配齐了才轮到客户2。
店B
采用异步
的方式:客户1去餐厅点餐付款之后,在旁边等餐。客户1等餐的同时,就轮到客户2点餐了。
This is 同步 && 异步,单线程 and 多线程 ;
结语:
别人在痛苦之中沉默不言,上帝却让我说出我的烦恼。——歌德