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

免费开商城网站wordpress 开关 边栏 选择 模板

免费开商城网站,wordpress 开关 边栏 选择 模板,seo 网站地图,任务发布网站建设我这里先不说和C之间的性能差距#xff0c;而是展开说JavaScript递归优化问题#xff0c;有人问我为什么不说性能差距#xff0c;我#xff1a;#xff1f;#xff1f;#xff1f;这个问题就跟问地球为什么是圆的一样(明摆着)传统的递归函数#xff0c;比如:function a…我这里先不说和C之间的性能差距而是展开说JavaScript递归优化问题有人问我为什么不说性能差距我这个问题就跟问地球为什么是圆的一样(明摆着)传统的递归函数比如:function a(){return a()}这是一个经典的递归在函数a内部调用自身调用栈的机制如下:每调用一个函数解释器就会把该函数添加进调用栈并开始执行.正在调用栈中执行的函数还调用了其它函数那么新函数也将会被添加进调用栈一旦这个函数被调用便会立即执行.当前函数执行完毕后解释器将其清出调用栈继续执行当前执行环境下的剩余的代码.当分配的调用栈空间被占满时会引发“堆栈溢出”错误.这里我们做一个测试尝试运行这个递归函数找出调用栈深度:let index 0function a(){index 1console.log(index)return a()}执行结果如下:// 省略多行输出 12559 12560 12561 12562 12563 Uncaught RangeError: Maximum call stack size exceededat console.X.t. [as log] (init.js:1)这里可以看出当递归深度达到12563的时候调用栈爆掉了平时使用是没有问题的但是对于某些特殊或者极端情况你又有相似需求的情况下怎么样突破这个调用栈限制做到永不爆栈呢这里需要一个比较hack的写法, 我们对上面的递归函数进行一下改造:let index 0async function a(){await undefinedindex 1console.log(index)return await a()}我们来执行一下看一下结果:// 省略多行输出 100590 100591 100592// 省略多行输出事实上这个递归函数永远不会停止它会一直执行下去也没有爆栈这是一个神奇的优化可以让你写出非常大深度的递归而不会出现问题这个优化的关键就是:async function() { await undefined }首先将递归函数改为async函数然后在内部最好第一行 await undefined这个操作的原理就是1 async创建微任务队列然后执行器执行当前队列.2此时遇到await undefined其实这个写法等同于await (async () {})和await Promise.resolve(setTimeout)这几种写法效果等同用unedfined只是为了在实现同样效果的情况下更简洁既然已经等同了那就从这三个写法分析起.3此时执行器发现第一个任务完全没有等待马上完成了但是执行器发现后面的任务是需要等待的并不会马上完成.4这时候执行器为了microtask(也就是协程)调度的合理优化不会让这个微任务队列始终占有这个execution而是会把当前微任务队列转移到别的execution去执行(您几位走得慢请去那边空闲的地方走).5转移execution带来的操作就是因为没办法直接转移调用栈所以会先将当前调用栈入堆然后把任务队列转移到别的execution.6然后队列里面接下来的任务全部都是使用新创建的execution去执行.这个操作的本意就是为了让当前栈入堆而且这个写法在C#和Kotlin里面是完全通用的因为这3个语言的异步方案都是基本类似而这个写法来自Rust群一位群友的发现当时我看到这种写法的时候也表示了惊奇然后对于递归大面积使用这种写法目前没有发现什么问题.这两天发现有人星风雪月对执行机制有很深的成见所以我这里使用Node.JS的async hooks做了一下异步执行的调试这是测试代码:const async_hooks require(async_hooks)let index 0let print_buffer /*** async hooks会追踪async调用,* 而console.log使用异步输出,* 所以这里使用同步方法模拟console*/function println(log) {print_buffer log \n}/* 创建钩子 */async_hooks.createHook({init(asyncId, type, triggerAsyncId) {const eid async_hooks.executionAsyncId()println(init: *********************************)println(init: triggerAsyncId triggerAsyncId)println(init: executionAsyncId eid)println(init: asyncId asyncId)println(init: type type)}}).enable()/*********** 测试区 **********/async function A() {/* 为了观察方便只执行2次 */println(A: runing)index 1if (index 2) return undefined// 有优化递归 await undefinedreturn await A()}/*********** 测试区 **********/A().then(() {console.log(print_buffer)})执行之后的输出:init: *********************************init: triggerAsyncId 1init: executionAsyncId 1init: asyncId 2init: type PROMISEA: runinginit: *********************************init: triggerAsyncId 2init: executionAsyncId 1init: asyncId 3init: type PROMISEinit: *********************************init: triggerAsyncId 3init: executionAsyncId 1init: asyncId 4init: type PROMISEinit: *********************************init: triggerAsyncId 2init: executionAsyncId 1init: asyncId 5init: type PROMISEinit: *********************************init: triggerAsyncId 4init: executionAsyncId 4init: asyncId 6init: type PROMISEA: runinginit: *********************************init: triggerAsyncId 6init: executionAsyncId 4init: asyncId 7init: type PROMISE这里看executionAsyncId标志这个是当前执行器的ID这里可以看到当经过await undefined之后, 执行器从1变成了4说明这里发生了execution转移下面我修改一下代码变成不优化的写法:// 无优化递归// await undefinedreturn await A()我这里将await undefined删除再来执行看看会是什么情况:init: *********************************init: triggerAsyncId 1init: executionAsyncId 1init: asyncId 2init: type PROMISEA: runinginit: *********************************init: triggerAsyncId 1init: executionAsyncId 1init: asyncId 3init: type PROMISEA: runinginit: *********************************init: triggerAsyncId 3init: executionAsyncId 1init: asyncId 4init: type PROMISEinit: *********************************init: triggerAsyncId 2init: executionAsyncId 1init: asyncId 5init: type PROMISE再看executionAsyncId这里始终是使用1去执行所以没有转移execution执行这里就很能说明问题了await undefined可以转移执行器执行让当前栈入堆这样可以使调用栈不会溢出达到深递归优化的目的.对于评论区朋友说明这种方式会阻塞macrotask所以不推荐这种写法我这里并不表示完全反对意见我这里来说一下我自己的看法异步任务归属microtask而其他事件回调归属macrotaskmicrotask的优先级本身就比macrotask要高所以肯定是microtask先执行然后才轮到macrotask像setTimeout(0)这种本身就是属于macrotask肯定要等到microtask执行完成之后才能执行不过这确实会带来一个问题就是对已经运行的macrotask产生时间分辨率精度影响比如定时器偏移定时器不会精准得按时间分片执行任务所以这种写法见仁见智你如果需要精确macrotask执行的场景还是慎用.
http://www.yutouwan.com/news/435941/

相关文章:

  • 网站后台密码存在哪wap网站如何制作
  • 小牛在线网站建设哪里网站建设专业
  • 网站建设销售员工作内容北京网站制作公司报价
  • wordpress站内搜索慢网络seo天津
  • 静态网站开发百科怎么用自己电脑做网站
  • 元素网站没有域名可以建网站吗
  • 公众平台如何做网站电脑系统优化软件
  • 强大的网站设计制作新乡市建设工程网站
  • 怎么做虚拟的网站长春三合一网站建设
  • 汽车网站建设的目的海阳有没有做企业网站的
  • 德语网站建设汽车之家2023官网
  • wordpress获取gallery怎么做好网站搜索引擎优化
  • 网站制作完成中卫网红大型蹦床设备
  • 能源门户网站建设网站建设怎样
  • 360网站推广官网苏州保洁公司哪家好一点
  • 郑州网站优化外包成品短视频app源码的下载方法
  • mt7620a做网站网站顶一下代码
  • 企业网站带后台模板网页设计流程步骤
  • 新建的网站怎么做seo优化东莞拓步网站建设
  • 做网站策划计划书郑州市网站和公众号建设
  • 太原云起时网站建设pc网站开发工具
  • 为什么要建立企业网站动漫技术制作专业
  • 织梦装修网站模板建设银行网站登陆不上去
  • 淄博 建设网站网站建设与制作软件
  • 贵州省都匀市网站建设网站视觉规范
  • 装修设计师网站wordpress 查询当月
  • 网站建设所需的基本条件品牌网站建设咨询
  • 迅博威网站建设ps制作网站首页教程
  • 小蘑菇网站开发平面设计素材免费网站有哪些
  • 本地搭建多个网站查找网站备案号