最近在学习vuejs设计与实现的编译器

忧虑

在代码里面有大量的while这样的状态机,一不小心就会出现死循环。这让我非常的忧虑。

我当下的问题是:

  • 如何在遇到死循环时候,及时中断
  • 如何在遇到是循环的时候,可以定位到时那个函数出问题
  • 如何在不影响原代码【逻辑】的情况下(非不新增代码,而是不影响原来代码的逻辑),中断改死循环

我在想一个问题

能否可以捕获到【死循环】。在检测到有死循环的时候,主动中断程序,并报告当前的死循环的程序的函数的名字。

这里的捕获是在不影响原代码的情况下,可以监听到死循环,并主动中断,并暴露死循环的函数名字。

当时经过几次尝试,例如给程序再包裹一个函数或注入代码,我发现好像都有些不大如意的地方。

嗯,那如果抽离这个检测死循环的代码到独立函数,且让有while的程序自己调用,是否就可以一定层度的减少心智压力以及更好的debug呢?

函数名字

首先,我们需要得到运行函数的名字,js并没有提供这样的功能,但是函数的arguments.callee却可以拿到整个函数内容的文本

例如

function a(){
//dosomeconsole.log(arguments.callee.toString())
}

执行代码a()后打印出来的内容是

得到的就是字符串

'function a(){
//dosome
 console.log(arguments.callee.toString())
}'

弊端

但是这有个弊端,如果代码是匿名函数,就拿不到函数名字,例如下面这样的代码,虽然复制给了变量a,但是函数本身是匿名函数

var a=function (){
//dosomeconsole.log(arguments.callee.toString())
}

因为函数是个匿名函数,得到的字符串如下,这种情况就需要用户自己传递过来了

'function(){
//dosome
 console.log(arguments.callee.toString())
}'

正则

那我们可以使用正则拿到函数名字

let str = arguments.callee.toString();var re = /^function\s*(\w+)\(/ig;var matches = re.exec(str);let fnName = matches[1];

死循环的特征是什么?

一个函数一直的不断的执行!!

如何判断呢?

如果在n秒内不断的执行某个函数那就可以认为他是死循环
我们可以用两个时间的间隔来判断这个函数执行了多久,如果大于某个时间,就让他break;

分解

那确定了方案后开始,对这个抽离的函数进行分解

  • 需要维护开始时间,结束时间
  • 需要更新结束时间
  • 需要为何死亡时间
  • 需要提供判断是否时死循环的函数

实现代码如下:

  var deadLoopCatch = function(argument, runFnName, deadLoopTimeLimit = 5000) {let fnName;if (runFnName) {fnName = runFnName;} else {let str = argument.callee.toString();var re = /^function\s*(\w+)\(/ig;var matches = re.exec(str);if (matches && matches[1]) {fnName = matches[1];} else {//如果是匿名函数,且用户没有传递第二个参数的时候,警告console.warn("When the loop is an anonymous function, please pass the second parameter for function deadLoopCatch")fnName = "---UMKNOW--";}}//初始化开始时间和结束时间let startTime = endTime = new Date().getTime();let result = {fnName,_startTime: startTime,_endTime: endTime,_deadLoopTimeLimit: deadLoopTimeLimit,updateTime: () => {result._endTime = new Date().getTime();},isDeadLoop: () => {let isDeadLoop = result._endTime - result._startTime >= result._deadLoopTimeLimit;//这代码好像有一点弊端,如果这里不执行的话,还是会死循环console.log("deadLoopCatch:result._endTime - result._startTime", result._endTime - result._startTime)if (isDeadLoop) {console.error(`Function ${fnName} triggered an endless loop!`)}return isDeadLoop;}}return result;}

一般情况下while不会执行耗时操作,所以如果一个while执行超过5秒,我们认为他就是死循环了,当然这个时间可以根据自己的实际情况调整

代码使用:

var abc = function(a, b, c) {var i = 1;let deadLoopCatchInit = deadLoopCatch(arguments, 'abc', 1000);while (true) {deadLoopCatchInit.updateTime()if (deadLoopCatchInit.isDeadLoop()) {console.warn("强制中断", deadLoopCatchInit)break;}console.log("执行中....")}}abc()

另外一个方案

另外个简单debug方式,就是在while第一行使用console.log(“函数名字”) 这种方式也可以定位到死循环是哪一个代码,但是却无法避免死循环。

疑问点,console

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><p>为什么去掉地46行,死循环拦截就没效果了!!<span id="txt"></span></p><script>var deadLoopCatch = function(argument, runFnName, deadLoopTimeLimit = 5000) {let fnName;if (runFnName) {fnName = runFnName;} else {let str = argument.callee.toString();var re = /^function\s*(\w+)\(/ig;var matches = re.exec(str);if (matches && matches[1]) {fnName = matches[1];} else {//如果是匿名函数,且用户没有传递第二个参数的时候,警告console.warn("When the loop is an anonymous function, please pass the second parameter for function deadLoopCatch")fnName = "---UMKNOW--";}}//初始化开始时间和结束时间let startTime = endTime = new Date().getTime();let result = {fnName,_startTime: startTime,_endTime: endTime,_deadLoopTimeLimit: deadLoopTimeLimit,updateTime: () => {result._endTime = new Date().getTime();},isDeadLoop: () => {let isDeadLoop = result._endTime - result._startTime >= result._deadLoopTimeLimit;//这代码好像有一点弊端,如果这里不执行的话,还是会死循环//  console.log("deadLoopCatch:result._endTime - result._startTime", result._endTime - result._startTime)if (isDeadLoop) {console.error(`Function ${fnName} triggered an endless loop!`)}return isDeadLoop;}}return result;}window.onload = function() {const dom = document.querySelector("#txt")var abc = function(a, b, c) {var i = 1;let deadLoopCatchInit = deadLoopCatch(arguments, 'abc', 1000);while (true) {deadLoopCatchInit.updateTime()if (deadLoopCatchInit.isDeadLoop()) {console.warn("强制中断", deadLoopCatchInit)dom.innerHTML = `更新第(${i}次)后<b style='background:red;'>强制中断</b>了`break;}i++;dom.innerHTML = `更新第(${i}次)`console.log("执行中....")}}abc()}</script>
</body></html>

运行一下上面的代码后会得到个奇怪的线下console.log的运行会滞后,while已经结束了,html已经输出了“强制中断”,console打印还在不断的追赶

console延后执行了

貌似console是个微任务的赶脚,这一定程度上也说的通,因为本来是用来调试的,不堵塞住流程代码也是应该的。

js 死循环代码debug相关推荐

  1. 分享63个JS幻灯片代码,总有一款适合您

    分享63个JS幻灯片代码,总有一款适合您 63个JS幻灯片代码下载链接:https://pan.baidu.com/s/1tWjsZD6ZiHGiXYmDOqxqgA?pwd=nwl2  提取码:nw ...

  2. 分享99个JS幻灯片代码,总有一款适合您

    分享99个JS幻灯片代码,总有一款适合您 99个JS幻灯片代码下载链接:https://pan.baidu.com/s/1n8UQ41cem0GmgsOXCq9kMw?pwd=m5zf  提取码:m5 ...

  3. 分享78个JS相册代码,总有一款适合您

    分享78个JS相册代码,总有一款适合您 78个JS相册代码下载链接:https://pan.baidu.com/s/1rV_Mk-AF-bCLgwIccvrmAQ?pwd=y4el  提取码:y4el ...

  4. 分享116个JS图片代码,总有一款适合您

    分享116个JS图片代码,总有一款适合您 116个JS图片代码下载链接:https://pan.baidu.com/s/1ebJsZ5s3GAhetqfJiA1ohg?pwd=e973  提取码:e9 ...

  5. 分享117个JS图片代码,总有一款适合您

    分享117个JS图片代码,总有一款适合您 117个JS图片代码下载链接:https://pan.baidu.com/s/1iIFGOhPNjUIaStGeVpY1IA?pwd=qwfw  提取码:qw ...

  6. 分享118个JS图片代码,总有一款适合您

    分享118个JS图片代码,总有一款适合您 118个JS图片代码下载链接:https://pan.baidu.com/s/1Tr5jX-Lr8Ytzx1lV4zr8nA?pwd=ji78  提取码:ji ...

  7. 分享126个JS图片代码,总有一款适合您

    分享126个JS图片代码,总有一款适合您 126个JS图片代码下载链接:https://pan.baidu.com/s/1tLDf9ukWCBOQU-Z2o7ofLA?pwd=3of5  提取码:3o ...

  8. Eclipse.自动提示--编写HTML/CSS/JS/JSP代码时自动提示的解决办法

    最近在做一个javaweb的项目,在eclipse中编写jsp代码时没有代码提示这个梗让人很头疼,之前一直写Java代码或者在Dreamweaver中写HTML代码时自动提示代码用起来特别爽,这突然间 ...

  9. html玫瑰花效果代码,html5渲染3D玫瑰花情人节礼物js特效代码

    情人节马上就要到来了,这里给程序员前端设计师们献上一个,html5渲染而成的3D玫瑰花js效果,可以作为虚拟的情人节礼物送给自己的爱人.支持html5的浏览器查看. 查看演示 下载资源: 16 次 下 ...

最新文章

  1. [MFC]多线程传参问题 [AfxBeginThread]
  2. 非计算机专业的人要如何学python?
  3. Android/Service详解/实例分析
  4. 【数字信号处理】相关函数与线性卷积关系 ( 卷积概念 | 相关函数概念 | 相关函数与线性卷积对比 | x(-m) 共轭 与 y(m) 的卷积就是两个信号 位移 m 的相关函数 )
  5. day-20: 安装软件包及rpm yum的介绍
  6. 码农创业,6年80万我是这样一步一步实现的,创业朋友共勉[终结篇3年后我再来]...
  7. 9、 InnoDB行锁
  8. C++学习-环境配置
  9. 华三ospf联动bfd_HCIE2020__路由交换专家__BFD综合实验
  10. 组合式应用新利器,事件网格“出圈”
  11. iOS开发拓展篇—CoreLocation地理编码
  12. Scrapy入门操作
  13. [WEB] 详解Ajax实现网页数据异步更新并实时自动刷新
  14. 苹果手机以旧换新价格表_苹果支持安卓手机以旧换新;索尼公司将更名;百度网盘推出“防误删”文件恢复服务...
  15. 产品经理会用到的常用术语大全
  16. 计算机换色带技巧,安装与更换针式打印机的色带的详细方法(图文教程)
  17. 微信文件指定应用打开并获取文件路径,以及遇到的一个坑
  18. C语言 :探究Char 到底是啥
  19. sox源码分析:sox_find_effect()
  20. [周鸿祎] 与其苟且活着,不如奋起抗争

热门文章

  1. 多步OLE DB操作产生错误
  2. 模板记录——赛前准备
  3. Everything 添加扫描 移动磁盘
  4. 压力太大,使人过早衰老
  5. 我的Redhat RHCSA/RHCE考试历程(心得)
  6. 王湛生留给CFO们的遗憾太多
  7. 常见的DCDC IC厂家
  8. netlink学习笔记(一)
  9. JS 节点的查找
  10. centos7中防火墙设置