Node.JS中异步与同步

首先,你得知道阻塞(blocking)和非阻塞(non-blocking)有啥区别。

你可以把Node.js看做一个人+一个团队:

JS的执行部分看做是一个人,叫它 a ;

调用libuv实现的IO操作的部分看做是一个团队,比如 arr ;

a 只有他自己1个人(单线程),他同一时间内只能干一件事,这部分是阻塞的,一项工作(语句)执行完才能执行下一项,比如一个for循环:

for(let t=0;t<10000;t++){

    console.log(t);

}

因为只有第一次循环执行完才能执行第二次循环,第二次循环执行完才能执行第三次……所以 a 重复做了一万次工作(累死),假设每个工作要做1秒,那么 a 做完所有工作要花1万秒。 这就叫做阻塞。

 

并不是所有工作都必须让 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 是被阻塞的,没法做其他事情(所以你自己愿意等谁也没办法!)。

如果这个你看的不是很清楚那么在

Node.JS中异步与同步_第1张图片

店A采用同步的方式: 客户1去餐厅点餐付款之后,要等客户1餐配齐了才轮到客户2。

店B采用异步的方式:客户1去餐厅点餐付款之后,在旁边等餐。客户1等餐的同时,就轮到客户2点餐了。

这就是同步与异步,单线程与多线程

你可能感兴趣的:(node.js,前端的那些事)