当前位置: 首页 > news >正文

dw制作一个手机网站模板下载企业宣传软文

dw制作一个手机网站模板下载,企业宣传软文,2015微信网站,高清做爰片免费观看网站上次我们分析过嵌套的process.nextTick的问题,会导致死循环,今天我们来看一下嵌套的setTimeout问题。分析之前我们先简单了解一下nodejs中定时器的架构。 1 相对超时时间一样的定时器放在同一个队列,比如刚开始时执行setTimeout(cb1, 5000)和…

上次我们分析过嵌套的process.nextTick的问题,会导致死循环,今天我们来看一下嵌套的setTimeout问题。分析之前我们先简单了解一下nodejs中定时器的架构。

1 相对超时时间一样的定时器放在同一个队列,比如刚开始时执行setTimeout(cb1, 5000)和过2秒后执行setTimeout(cb2, 5000);他们会在同一个队列中。即上图的List。
2 同一队列中,尾节点比头结点先到期。即cb1对应上图的节点1,cb2对应节点2。
3 同一队列中,每个节点记录了该定时节点的开始时间和相对超时时间,比如{开始时间:1,相对过期时间:5}和{开始时间:3,相对过期时间:5}。
4 每个List对象记录了当前队列最快到期的节点的绝对时间。即1+5=6。

了解了nodejs中定时器的大致实现后,我们开始看问题。假设我们有以下一段代码

function main() {setTimeout(() => {main();}, 1)
}
main();
setTimeout(() => {console.log(2)
},2);

以上代码的2会输出吗?我们开始分析这个问题,假设我们开始时间是0秒。那么以上代码执行完后有下图。

当1ms过去的时候,第一个队列先过期,这时候就会遍历队列1的节点执行对应的回调。根据代码这时候,会执行队列1的节点1。因为节点1的回调里又插入了一个新的节点。所以有下图。

当执行完节点的回调后,该节点就会被删除。有下图。

因为第一个队列非空,nodejs会继续遍历该队列,这时候有两种情况。执行队列1的节点1时消耗了1ms,那么这时候节点2也超时,如果消耗小于1ms,则节点2还没有超时。我们只讨论消耗了1ms的情况(因为如果消耗小于1ms,就会停止遍历队列,自然不会导致死循环)。我们把代码改一下

function main() {setTimeout(() => {main();// 做一些消耗cpu的操作。}, 1)
}
main();
setTimeout(() => {console.log(2)
},2);

我们在插入新节点之后,遍历下一个节点之前,做一些耗cpu的操作,保证遍历下一个节点时,他已经超时。但是执行以上代码,发现,2仍然会输出。即不会一直在遍历队列1导致死循环。为什么呢?看过《嵌套的process.nextTick问题》一文的同学可能想到,插入的队列和遍历的队列不是同一个。我们翻开nodejs的源码。看看到底是怎么回事。我们看一下nodejs是如何处理定时器的。

 // now为执行procesTimefunction processTimers(now) {nextExpiry = Infinity;let list;// 取出优先队列的根节点,即最快到期的节点while (list = timerListQueue.peek()) {// 最快到期的节点还没到期则,则全部节点都没有到期,不需要遍历了if (list.expiry > now) {nextExpiry = list.expiry;// 返回下一次过期的时间return refCount > 0 ? nextExpiry : -nextExpiry;}// 遍历队列的定时器listOnTimeout(list, now);}return 0;}

processTimers首先从优先队列中取出最快到期的节点所在队列。然后遍历该队列,假设这时候已经到期,nodejs会执行listOnTimeout遍历队列。我们看看listOnTimeout。

function listOnTimeout(list, now) {// 队列对应的相对过期时间,比如文中的1和2const msecs = list.msecs;let timer;// 遍历具有统一相对过期时间的队列while (timer = L.peek(list)) {// _idleStart为节点开始的时间,diff是从节点被插入开始已经过去的时间const diff = now - timer._idleStart;// 过期的时间比超时时间小,还没过期if (diff < msecs) {// 整个链表节点的最快过期时间等于当前还没过期节点的值,链表是有序的// 如果相差小于1ms过期,则取1ms后过期,比如setTimeout(cb,1.5)list.expiry = MathMax(timer._idleStart + msecs, now + 1);// 更新id,用于决定在优先队列里的位置list.id = timerListId++;// 调整过期时间后,当前链表对应的节点不一定是优先队列里的根节点了,可能有他更快到期,即当前链表需要往下沉timerListQueue.percolateDown(1);return;}// 准备执行用户设置的回调,删除这个节点L.remove(timer);// 执行回调}}

listOnTimeout遍历队列中的每一个节点,如果超时则先从队列中移除,然后执行回调。如果没有超时则修改该队列最快到期的时间为该节点的绝对超时时间。重点在于diff < msecs的判断和now。我们nodejs在处理定时器的过程中,now的值是不会变的,他的值是开始处理定时器任务时的时间点。所以如果我们在setTimeout中又插入一个新的节点时,他的开始时间会比now还大。这导致了const diff = now - timer._idleStart的值为负数。从而if (diff < msecs) 成立。所以就不会遍历后面的节点了。从而不会形成死循环。我们看到在setTimeout里即使插入了新节点,并且新节点也过期了,也不会在本轮事件循环执行,因为nodejs在处理定时器阶段的时候,不会实时更新now的值,从而导致他只会执行开启时间在now之前的定时器。在执行期间插入的节点无论是否已经过期。最快也只会在下一轮事件循环执行。

http://www.lbrq.cn/news/2553949.html

相关文章:

  • 做网站数据库表设计关键词百度网盘
  • 商品展示介绍网站源码柏乡seo快排优化
  • 全国十大装修公司windows优化大师有哪些功能
  • 手机代码网站有哪些问题吗沈阳优化推广哪家好
  • 上海人才引进网站百度一下你就知道移动官网
  • 怎么用IP做网站地址百姓网推广怎么收费标准
  • 国外wordpress主题破解版潍坊seo网络推广
  • 做网站什么空间好磁力神器
  • 备案的博客网站可以做别的吗缅甸最新新闻
  • 南通的网站建设品牌推广手段
  • 网站做加qq群链接地址谷歌引擎搜索入口
  • 免费速建网站关键词优化搜索排名
  • 公众号怎么做文章编辑短视频seo询盘获客系统软件
  • 全国旅游卡appseo网站搜索优化
  • 做付费网站站长全自动年赚30万免费推广网站排行榜
  • 大学新校区建设网站网络营销广告
  • app制作网站有哪些 请列举网站如何优化关键词排名
  • 网站备案注销申请表网站建设平台官网
  • 电商app开发哪家公司最好seo怎样优化网站
  • 外贸独立站建站推广沈阳线上教学
  • 垂直网站做益智类问答深圳网络推广外包公司
  • 秦皇岛网站开发报价长春百度网站优化
  • 嵊州网站设计北京网站建设东轩seo
  • 嘉兴哪家公司做网站比较好的东莞海外网络推广
  • 网站开发是前端还是后端软文标题和内容
  • 网站开发合同适用印花税360点睛实效平台推广
  • 怎么改网站模板百度推广关键词查询
  • 两学一做网站专栏怎么设置地产渠道12种拓客方式
  • 重庆注册公司代办机构北京seo方法
  • 网站做的好北京百度网站排名优化
  • WaitForSingleObject 函数参数影响及信号处理分析
  • (27)运动目标检测之对二维点集进行卡尔曼滤波
  • springcloud04——网关gateway、熔断器 sentinel
  • SpringBoot3.x入门到精通系列:1.1 简介与新特性
  • 33.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--财务服务--记账
  • AI学习笔记三十三:基于Opencv的单目标跟踪