资讯专栏INFORMATION COLUMN

问答方式学 Node.js

feng409 / 2689人阅读

摘要:对了,我记得你提到了,它是什么不是说使用的是吗,它和又有什么关系未完待续其他问答方式学一参考是用来做什么的厂长的回答更快的异步函数和

Q: 好了,我们继续谈谈 Node.js 吧,我记得上次说到了「非阻塞」和「事件驱动」,这引起了我的好奇心,但是又给我泼了一桶冷水,这两个词有点高端。

A:别急,我们先来看一个简单的场景:

人人网刷朋友新鲜事你应该用过吧?实现这样的功能有一种简单的方式,是让用户与服务器之间保持一个长轮询。

但是它与普通的 Ajax 不一样,服务器不会立马返回信息,它会先 hold 住,等待应该返回信息了,它才会返回信息(比如你的好友发了一条新的状态)。

从传统服务端来看(比如 Apache),每次一个新用户连到你的网站上,你的服务器得新开一个连接,每个连接都需要占用一个线程,这些线程大部分都是闲着的(比如等你的好友发状态,查数据库等),虽然它们是闲着的,但是照样占用了内存,也就是说,如果用户达到一定的规模,服务器的内存就会耗光而瘫痪。

解决办法有很多,比如说使用线程池,但是它依然是阻塞的,如果线程池里的所有线程都被阻塞(网速慢,被人恶意暂用)那么接下来的请求将会排队等待。

Node.js 就不相同了,它使用了「非阻塞」与「事件驱动」模型,你可以把它想象成一个 Event Loop 循环,这个循环会一直跑。一个新的请求来了,Event Loop 接收这个请求,然后交给其他线程,比如查询数据库,然后响应一个 callback,接着接收其他请求,而不是等待数据库结果的返回。

如果数据库返回了结果,服务端将会把它返回给客户端,并继续循环。这就是事件驱动:服务端只在有事情发生时,才会有相应的处理(或者是接受请求,或者是一些 callback)。

Q:这么看来,Node.js 的非阻塞和事件驱动,是基于这个 Event Loop 的?

A:是的,简单来讲,Node.js 的 Event Loop 是基于 libuv,而浏览器的 Event Loop 则是在 html5 规范 中定义,具体实现交给浏览器厂商。

Q:有趣了,还有两种 Event Loop。

A:对比来看,它们有点相似:

在浏览器中比较简单,值得注意的一点是,会在每个 tasks 之后,会把当前 microtask 队列里的任务都执行完:

Node.js 稍微复杂一点,每次 Event Loop 都需要经过六个阶段,每一个阶段之后,都会执行 nextTick、microtasks (resolved promise, 等):

   ┌───────────────────────┐
┌─>│        timers         │ <─── setTimeout/setInterval callback
│  └──────────┬────────────┘      ┌─────────────────────────┐
│             │                   │ nextTick queue          │
│             │ <───────────────  │                         │
│             │                   │ microTask queue         │
│  ┌──────────┴────────────┐      └─────────────────────────┘
│  │     I/O callbacks     │
│  └──────────┬────────────┘      ┌─────────────────────────┐
│             │                   │ nextTick queue          │
│             │ <───────────────  │                         │
│             │                   │ microTask queue         │
│  ┌──────────┴────────────┐      └─────────────────────────┘
│  │     idle, prepare     │ <─── 仅内部使用
│  └──────────┬────────────┘
│             │                   ┌─────────────────────────┐
│             │                   │ nextTick queue          │
│             │ <──────────────── │                         │
│             │                   │ microTask queue         │
│             │                   └─────────────────────────┘
│             │                   ┌─────────────────────────┐
│  ┌──────────┴────────────┐      │      incoming:          │
│  │         poll          │ <────┤      connections,       │
│  └──────────┬────────────┘      │      data, etc          │
│             │                   └─────────────────────────┘
│             │                   ┌─────────────────────────┐
│             │                   │ nextTick queue          │
│             │ <──────────────── │                         │
│             │                   │ microTask queue         │
│             │                   └─────────────────────────┘
│  ┌──────────┴────────────┐
│  │        check          │ <─── setImmediate callback
│  └──────────┬────────────┘      ┌─────────────────────────┐
│             │                   │ nextTick queue          │
│             │ <───────────────  │                         │
│             │                   │ microTask queue         │
│  ┌──────────┴────────────┐      └─────────────────────────┘
│  │    close callbacks    │ <─── eg: socket.on("close",func)
│  └──────────┬────────────┘      ┌─────────────────────────┐
│             │                   │ nextTick queue          │
│             │ <───────────────  │                         │
└─────────────┴                   │ microTask queue         │
                                  └─────────────────────────┘

来一段简单的代码,猜猜浏览器(Chrome)和 Node.js 分别输出什么:

console.log("start");

setTimeout(() => {
  console.log("timer1");
  Promise.resolve().then(() => {
      console.log("promise1");
  });
}, 0);

setTimeout(() => {
  console.log("timer2");
  Promise.resolve().then(() => {
    console.log("promise2");
  });
}, 0);

console.log("end");
Q:浏览器 (Chrome) 中肯定是输出 start、end、time1、promise1、time2、promise2,至于 Node.js 中,我猜也是一样的吧?

A:我们先来验证一下:

浏览器中:

start
end
timer1
promise1
timer2
promise2

Node.js 中:

start
end
timer1
timer2
promise1
promise2

看来和想象中的不一样,别急,看个动图就会明白了:

浏览器中:

Node.js 中:

Q:原来是这样,那如果在每个 setTimeout callback 里加上 process.nextTick 那么是比 Promise.then 先执行?

A:是的,还记得上面所说过的吗,在每个阶段后都会执行 nextTick queue 以及 micktasks queue,nextTick queue 的优先级比 micktasks queue 高。

Q:我懂了。对了,我记得你提到了 libuv,它是什么?不是说 Node.js 使用的是 v8 吗,它和 v8 又有什么关系?

A:...

未完待续...

其他

问答方式学 Node.js(一)

参考

https://blog.csdn.net/wtopps/...

Node.js 是用来做什么的? - 厂长的回答

Promises, Next-Ticks and Immediates— NodeJS Event Loop Part 3

更快的异步函数和 Promise

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/101074.html

相关文章

  • Vue.js新手入门指南[转载]

    摘要:就是一个用于搭建类似于网页版知乎这种表单项繁多,且内容需要根据用户的操作进行修改的网页版应用。单页应用程序顾名思义,单页应用一般指的就是一个页面就是应用,当然也可以是一个子应用,比如说知乎的一个页面就可以视为一个子应用。 最近在逛各大网站,论坛,以及像SegmentFault等编程问答社区,发现Vue.js异常火爆,重复性的提问和内容也很多,楼主自己也趁着这个大前端的热潮,着手学习了一...

    MartinHan 评论0 收藏0
  • 前端习资源整理

    稍微整理了一下自己平时看到的前端学习资源,分享给大家。 html MDN:Mozilla开发者网络 SEO:前端开发中的SEO css 张鑫旭:张鑫旭的博客 css精灵图:css精灵图实践 栅格系统:详解CSS中的栅格系统 媒体查询:css媒体查询用法 rem布局:手机端页面自适应布局 移动前端开发之viewport的深入理解:深入理解viewport 淘宝前端布局:手机淘宝移动端布局 fl...

    siberiawolf 评论0 收藏0
  • 个人分享--web前端习资源分享

    摘要:前言月份开始出没社区,现在差不多月了,按照工作的说法,就是差不多过了三个月的试用期,准备转正了一般来说,差不多到了转正的时候,会进行总结或者分享会议那么今天我就把看过的一些学习资源主要是博客,博文推荐分享给大家。 1.前言 6月份开始出没社区,现在差不多9月了,按照工作的说法,就是差不多过了三个月的试用期,准备转正了!一般来说,差不多到了转正的时候,会进行总结或者分享会议!那么今天我就...

    sherlock221 评论0 收藏0
  • 【1024程序员节】程序员,你编程的初衷是什么?

    摘要:虽然程序员有时候很喜欢自黑风格也比较独特,但程序员也只是会编程的普通人,和其他的厨师教师公务员并没有什么区别。 前言 今天是1024程序员节,中国500w+的程序员今天可以享受一天专属的节日,网络上也有各种庆祝方式: 一些公司祭出了程序员鼓励师 showImg(https://segmentfault.com/img/remote/1460000016788859); 一些公司给程序员...

    DataPipeline 评论0 收藏0

发表评论

0条评论

feng409

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<