zoukankan      html  css  js  c++  java
  • setTimeout 导致的浏览器假死

     问题

       前几天,同事遇到一个浏览器假死的问题。就是浏览器在响应一个请求的时候,就突然不响应时间,进入假死状态,Cup也飙升到100%. 但是这个问题只出现在IE浏览器,chrome和Firefox等其他浏览器正常。

    原因

      Js 代码里面,看着也没有什么耗时的操作和后台异步调用。没办法,只能从响应事件的最开始一步一步调查。经过一番调试之后,问题定位在setTimeout 函数。当把setTimeout 里面执行的函数去掉之后,立马就不会出现这种情况。查看setTimeout 里面调用的函数,发现里面JS中有一些的DOM操作,函数里面还进行了html的拼接。难道是这个原因导致的。于是网上查原因:当一段JS脚本长时间占用着处理机就会挂起浏览器的GUI更新,而后面的事件响应也被排在队列中得不到处理,从而造成了浏览器被锁定进入假死状态。说白了就是:浏览器无法在渲染页面的同时执行js。在setTimeout 函数里面,确实有一些拼接html 和操作dom 的情况。可能就是js在执行的时候,js代码里面又有一些拼接html 的操作。导致浏览器无法渲染页面,而js 里面在操作这个页面的内容。导致浏览器卡死。

    浏览器的内核处理方式:

      浏览器的内核是多线程的,它们在内核制控下相互配合以保持同步,一个浏览器至少实现三个常驻线程:javascript引擎线程,GUI渲染线程,浏览器事件触发线程。

    1. JavaScript引擎是基于事件驱动单线程执行的,JS引擎一直等待着任务队列中任务的到来然后加以处理,浏览器无论再什么时候都只有一个JS线程在运行JS程序。
    2. GUI 渲染线程负责渲染浏览器界面,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。但需要注意 GUI渲染线程与JS引擎是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
    3. 事件触发线程,当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。

      明白了浏览器内核处理方式,就可以理解浏览器为什么会进入假死状态了,当一段JS脚本长时间占用着cpu 时间时,就会挂起浏览器的GUI更新,而后面的事件响应也被排在队列中得不到处理,从而造成了浏览器被锁定进入假死状态。另外JS脚本中进行了DOM操作,一旦JS调用结束就会马上进行一次GUI渲染,然后才开始执行下一个任务,所以JS中大量的DOM操作也会导致事件响应缓慢甚至卡死浏览器。

      这个文章写得更加透彻:http://www.nowamagic.net/librarys/veda/detail/787

  • 相关阅读:
    面试题25二叉树中和为某一值得路径+递归函数详细解析
    [Codeforces 1199D]Welfare State(线段树)
    [Codeforces 1199C]MP3(离散化+二分答案)
    [Codeforces 1191D] Tokitsukaze, CSL and Stone Game(博弈论)
    [Codeforces 639F] Bear and Chemistry (Tarjan+虚树)(有详细注释)
    [HDU5807] [BestCoder Round #86 1004] Keep In Touch (DP)
    [Codeforces712D] Memory and Scores(DP+前缀和优化)(不用单调队列)
    [Codeforces722E] Research Rover (dp+组合数学)
    [POJ3612] Telephone Wire(暴力dp+剪枝)
    [Codeforces600E] Lomsat gelral(树上启发式合并)
  • 原文地址:https://www.cnblogs.com/zhangweizhong/p/3854025.html
Copyright © 2011-2022 走看看