admin 发表于 2018-12-5 10:58:54

如何优雅处理前端异常?

<div class="post-content markdown" itemprop="articleBody" style="font-size: 1.7rem; text-rendering: optimizeLegibility; letter-spacing: -0.3px; font-family: Merriweather, serif; color: rgb(93, 104, 111); margin-top: 20px; overflow: hidden;"><div class="main-content-wrap" style="max-width: 750px; margin-right: auto; margin-left: auto; padding-right: 20px; padding-left: 20px;"><p style="margin-top: 1.5em;">前端一直是距离用户最近的一层,随着产品的日益完善,我们会更加注重用户体验,而前端异常却如鲠在喉,甚是烦人。<br><a id="more" style="cursor: pointer; color: rgb(52, 158, 243);"></a></p><h4 id="一、为什么要处理异常?" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#一、为什么要处理异常?" class="headerlink" title="一、为什么要处理异常?" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>一、为什么要处理异常?</h4><div class="alert success" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(77, 198, 87); border-right: none rgb(77, 198, 87); border-bottom: none rgb(77, 198, 87); border-image: initial; border-left: 3px solid rgb(77, 198, 87); background-color: rgb(239, 250, 240); content: &quot;&quot;;"><p>异常是不可控的,会影响最终的呈现结果,但是我们有充分的理由去做这样的事情。</p></div><p style="margin-top: 1.5em;">1.增强用户体验;<br>2.远程定位问题;<br>3.未雨绸缪,及早发现问题;<br>4.无法复线问题,尤其是移动端,机型,系统都是问题;<br>5.完善的前端方案,前端监控系统;</p><p style="margin-top: 1.5em;">对于&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">JS</code>&nbsp;而言,我们面对的仅仅只是异常,异常的出现不会直接导致&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">JS</code>&nbsp;引擎崩溃,最多只会使当前执行的任务终止。</p><h4 id="二、需要处理哪些异常?" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#二、需要处理哪些异常?" class="headerlink" title="二、需要处理哪些异常?" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>二、需要处理哪些异常?</h4><p style="margin-top: 1.5em;">对于前端来说,我们可做的异常捕获还真不少。总结一下,大概如下:</p><ul style="margin-bottom: 0.5em;"><li><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">JS</code>&nbsp;语法错误、代码异常</li><li><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">AJAX</code>&nbsp;请求异常</li><li>静态资源加载异常</li><li><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Promise</code>&nbsp;异常</li><li><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Iframe</code>&nbsp;异常</li><li>跨域 Script error</li><li>崩溃和卡顿</li></ul><div class="alert info" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(52, 158, 243); border-right: none rgb(52, 158, 243); border-bottom: none rgb(52, 158, 243); border-image: initial; border-left: 3px solid rgb(52, 158, 243); background-color: rgb(230, 243, 254);"><p><a href="http://jartto.wang/2018/11/20/js-exception-handling/" style="color: rgb(52, 158, 243); text-decoration-line: none;">下面</a>我会针对每种具体情况来说明如何处理这些异常。</p></div><h4 id="三、Try-Catch-的误区" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#三、Try-Catch-的误区" class="headerlink" title="三、Try-Catch 的误区" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>三、Try-Catch 的误区</h4><p style="margin-top: 1.5em;"><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">try-catch</code>&nbsp;只能捕获到同步的运行时错误,对语法和异步错误却无能为力,捕获不到。<br>1.同步运行时错误:<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">try</span> {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">let</span> name = <span class="string" style="color: rgb(24, 54, 145);">'jartto'</span>;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(nam);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">} <span class="keyword" style="color: rgb(167, 29, 93);">catch</span>(e) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(<span class="string" style="color: rgb(24, 54, 145);">'捕获到异常:'</span>,e);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">输出:<br></p><figure class="highlight plain" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">捕获到异常: ReferenceError: nam is not defined</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    at &lt;anonymous&gt;:3:15</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">2.不能捕获到语法错误,我们修改一下代码,删掉一个单引号:<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">7</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">try</span> {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">let</span> name = <span class="string" style="color: rgb(24, 54, 145);">'jartto;</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="string" style="color: rgb(24, 54, 145);">console.log(nam);</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="string" style="color: rgb(24, 54, 145);">} catch(e) {</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="string" style="color: rgb(24, 54, 145);"></span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="string" style="color: rgb(24, 54, 145);">console.log('</span>捕获到异常:<span class="string" style="color: rgb(24, 54, 145);">',e);</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="string" style="color: rgb(24, 54, 145);">}</span></div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">输出:<br></p><figure class="highlight plain" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">Uncaught SyntaxError: Invalid or unexpected token</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><div class="alert info" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(52, 158, 243); border-right: none rgb(52, 158, 243); border-bottom: none rgb(52, 158, 243); border-image: initial; border-left: 3px solid rgb(52, 158, 243); background-color: rgb(230, 243, 254);"><p>不过语法错误在我们开发阶段就可以看到,应该不会顺利上到线上环境。</p></div><p style="margin-top: 1.5em;">3.异步错误<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">7</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">try</span> {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="literal" style="color: rgb(0, 134, 179);">undefined</span>.map(<span class="function"><span class="params">v</span> =&gt;</span> v);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}, <span class="number" style="color: rgb(0, 134, 179);">1000</span>)</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">} <span class="keyword" style="color: rgb(167, 29, 93);">catch</span>(e) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(<span class="string" style="color: rgb(24, 54, 145);">'捕获到异常:'</span>,e);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">我们看看日志:<br></p><figure class="highlight plain" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">Uncaught TypeError: Cannot read property 'map' of undefined</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    at setTimeout (&lt;anonymous&gt;:3:11)</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">并没有捕获到异常,这是需要我们特别注意的地方。</p><h4 id="四、window-onerror-不是万能的" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#四、window-onerror-不是万能的" class="headerlink" title="四、window.onerror 不是万能的" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>四、window.onerror 不是万能的</h4><p style="margin-top: 1.5em;">当&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">JS</code>&nbsp;运行时错误发生时,<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">window</code>&nbsp;会触发一个&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">ErrorEvent</code>&nbsp;接口的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">error</code>&nbsp;事件,并执行&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">window.onerror()</code>。<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">7</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">8</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">9</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">10</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">11</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 672px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 672px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">/**</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">* @param {String}message    错误信息</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">* @param {String}source    出错文件</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">* @param {Number}lineno    行号</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">* @param {Number}colno    列号</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">* @param {Object}errorError对象(对象)</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">*/</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">window</span>.onerror = <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span>(<span class="params">message, source, lineno, colno, error</span>) </span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">   <span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(<span class="string" style="color: rgb(24, 54, 145);">'捕获到异常:'</span>,{message, source, lineno, colno, error});</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">1.首先试试同步运行时错误<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">7</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">8</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">9</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">window</span>.onerror = <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span>(<span class="params">message, source, lineno, colno, error</span>) </span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">// message:错误信息(字符串)。</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">// source:发生错误的脚本URL(字符串)</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">// lineno:发生错误的行号(数字)</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">// colno:发生错误的列号(数字)</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">// error:Error对象(对象)</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(<span class="string" style="color: rgb(24, 54, 145);">'捕获到异常:'</span>,{message, source, lineno, colno, error});</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">Jartto;</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">可以看到,我们捕获到了异常:<br><img src="https://raw.githubusercontent.com/chenfengyanyu/my-web-accumulation/master/images/js-exception/error1.png" alt="error1" style="display: block; width: auto; max-width: 100%;"></p><p style="margin-top: 1.5em;">2.再试试语法错误呢?<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">window</span>.onerror = <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span>(<span class="params">message, source, lineno, colno, error</span>) </span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(<span class="string" style="color: rgb(24, 54, 145);">'捕获到异常:'</span>,{message, source, lineno, colno, error});</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">let</span> name = <span class="string" style="color: rgb(24, 54, 145);">'Jartto</span></div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">控制台打印出了这样的异常:<br></p><figure class="highlight plain" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">Uncaught SyntaxError: Invalid or unexpected token</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><div class="alert danger" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(245, 49, 29); border-right: none rgb(245, 49, 29); border-bottom: none rgb(245, 49, 29); border-image: initial; border-left: 3px solid rgb(245, 49, 29); background-color: rgb(254, 236, 234);"><p>什么,竟然没有捕获到语法错误?</p></div><p style="margin-top: 1.5em;">3.怀着忐忑的心,我们最后来试试异步运行时错误:<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">window</span>.onerror = <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span>(<span class="params">message, source, lineno, colno, error</span>) </span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(<span class="string" style="color: rgb(24, 54, 145);">'捕获到异常:'</span>,{message, source, lineno, colno, error});</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    Jartto;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">});</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">控制台输出了:<br></p><figure class="highlight plain" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">捕获到异常: {message: "Uncaught ReferenceError: Jartto is not defined", source: "http://127.0.0.1:8001/", lineno: 36, colno: 5, error: ReferenceError: Jartto is not defined</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    at setTimeout (http://127.0.0.1:8001/:36:5)}</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">4.接着,我们试试网络请求异常的情况:<br></p><figure class="highlight html" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">7</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;<span class="name" style="color: rgb(99, 163, 92);">script</span>&gt;</span><span class="undefined"></span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="javascript"><span class="built_in">window</span>.onerror = <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span>(<span class="params">message, source, lineno, colno, error</span>) </span>{</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="javascript">    <span class="built_in">console</span>.log(<span class="string" style="color: rgb(24, 54, 145);">'捕获到异常:'</span>,{message, source, lineno, colno, error});</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="javascript">    <span class="keyword" style="color: rgb(167, 29, 93);">return</span> <span class="literal">true</span>;</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="undefined">}</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="undefined"></span><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;/<span class="name" style="color: rgb(99, 163, 92);">script</span>&gt;</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;<span class="name" style="color: rgb(99, 163, 92);">img</span> <span class="attr" style="color: rgb(121, 93, 163);">src</span>=<span class="string" style="color: rgb(24, 54, 145);">"./jartto.png"</span>&gt;</span></div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><div class="alert warning" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(245, 170, 10); border-right: none rgb(245, 170, 10); border-bottom: none rgb(245, 170, 10); border-image: initial; border-left: 3px solid rgb(245, 170, 10); background-color: rgb(253, 241, 216);"><p>我们发现,不论是静态资源异常,或者接口异常,错误都无法捕获到。</p></div><p style="margin-top: 1.5em;">补充一点:<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">window.onerror</code>&nbsp;函数只有在返回&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">true</code>&nbsp;的时候,异常才不会向上抛出,否则即使是知道异常的发生控制台还是会显示&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Uncaught Error: xxxxx</code><br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">7</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">window</span>.onerror = <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span>(<span class="params">message, source, lineno, colno, error</span>) </span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(<span class="string" style="color: rgb(24, 54, 145);">'捕获到异常:'</span>,{message, source, lineno, colno, error});</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="keyword" style="color: rgb(167, 29, 93);">return</span> <span class="literal" style="color: rgb(0, 134, 179);">true</span>;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    Jartto;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">});</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">控制台就不会再有这样的错误了:<br></p><figure class="highlight plain" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">Uncaught ReferenceError: Jartto is not defined</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    at setTimeout ((index):36)</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">需要注意:<br><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">onerror</code>&nbsp;最好写在所有&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">JS</code>&nbsp;脚本的前面,否则有可能捕获不到错误;<br><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">onerror</code>&nbsp;无法捕获语法错误;</p><p style="margin-top: 1.5em;">到这里基本就清晰了:在实际的使用过程中,<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">onerror</code>&nbsp;主要是来捕获预料之外的错误,而&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">try-catch</code>则是用来在可预见情况下监控特定的错误,两者结合使用更加高效。</p><div class="alert warning" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(245, 170, 10); border-right: none rgb(245, 170, 10); border-bottom: none rgb(245, 170, 10); border-image: initial; border-left: 3px solid rgb(245, 170, 10); background-color: rgb(253, 241, 216);"><p>问题又来了,捕获不到静态资源加载异常怎么办?</p></div><h4 id="五、window-addEventListener" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#五、window-addEventListener" class="headerlink" title="五、window.addEventListener" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>五、window.addEventListener</h4><p style="margin-top: 1.5em;">当一项资源(如图片或脚本)加载失败,加载资源的元素会触发一个&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Event</code>&nbsp;接口的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">error</code>&nbsp;事件,并执行该元素上的<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">onerror()</code>&nbsp;处理函数。这些&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">error</code>&nbsp;事件不会向上冒泡到&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">window</code>&nbsp;,不过(至少在&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Firefox</code>&nbsp;中)能被单一的<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">window.addEventListener</code>&nbsp;捕获。<br></p><figure class="highlight html" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;<span class="name" style="color: rgb(99, 163, 92);">scritp</span>&gt;</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;">window.addEventListener('error', (error) =&gt; {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    console.log('捕获到异常:', error);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}, true)</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;/<span class="name" style="color: rgb(99, 163, 92);">script</span>&gt;</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;<span class="name" style="color: rgb(99, 163, 92);">img</span> <span class="attr" style="color: rgb(121, 93, 163);">src</span>=<span class="string" style="color: rgb(24, 54, 145);">"./jartto.png"</span>&gt;</span></div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">控制台输出:<br><img src="https://raw.githubusercontent.com/chenfengyanyu/my-web-accumulation/master/images/js-exception/error2.png" alt="error2" style="display: block; width: auto; max-width: 100%;"></p><p style="margin-top: 1.5em;">由于网络请求异常不会事件冒泡,因此必须在捕获阶段将其捕捉到才行,但是这种方式虽然可以捕捉到网络请求的异常,但是无法判断&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">HTTP</code>&nbsp;的状态是&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">404</code>&nbsp;还是其他比如&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">500</code>&nbsp;等等,所以还需要配合服务端日志才进行排查分析才可以。</p><p style="margin-top: 1.5em;">需要注意:</p><ul style="margin-bottom: 0.5em;"><li>不同浏览器下返回的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">error</code>&nbsp;对象可能不同,需要注意兼容处理。</li><li>需要注意避免&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">addEventListener</code>&nbsp;重复监听。</li></ul><h4 id="六、Promise-Catch" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#六、Promise-Catch" class="headerlink" title="六、Promise Catch" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>六、Promise Catch</h4><div class="alert info" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(52, 158, 243); border-right: none rgb(52, 158, 243); border-bottom: none rgb(52, 158, 243); border-image: initial; border-left: 3px solid rgb(52, 158, 243); background-color: rgb(230, 243, 254);"><p>在&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">promise</code>&nbsp;中使用&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">catch</code>&nbsp;可以非常方便的捕获到异步&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">error</code>&nbsp;,这个很简单。</p></div><p style="margin-top: 1.5em;">没有写&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">catch</code>&nbsp;的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Promise</code>&nbsp;中抛出的错误无法被&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">onerror</code>&nbsp;或&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">try-catch</code>&nbsp;捕获到,所以我们务必要在&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Promise</code>&nbsp;中不要忘记写&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">catch</code>&nbsp;处理抛出的异常。</p><p style="margin-top: 1.5em;">解决方案: 为了防止有漏掉的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Promise</code>&nbsp;异常,建议在全局增加一个对&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">unhandledrejection</code>&nbsp;的监听,用来全局监听<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Uncaught Promise Error</code>。使用方式:<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">window</span>.addEventListener(<span class="string" style="color: rgb(24, 54, 145);">"unhandledrejection"</span>, <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span>(<span class="params">e</span>)</span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(e);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">});</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">我们继续来尝试一下:<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">window</span>.addEventListener(<span class="string" style="color: rgb(24, 54, 145);">"unhandledrejection"</span>, <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span>(<span class="params">e</span>)</span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">e.preventDefault()</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(<span class="string" style="color: rgb(24, 54, 145);">'捕获到异常:'</span>, e);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">return</span> <span class="literal" style="color: rgb(0, 134, 179);">true</span>;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">});</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">Promise</span>.reject(<span class="string" style="color: rgb(24, 54, 145);">'promise error'</span>);</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">可以看到如下输出:<br><img src="https://raw.githubusercontent.com/chenfengyanyu/my-web-accumulation/master/images/js-exception/promise.png" alt="promise" style="display: block; width: auto; max-width: 100%;"></p><p style="margin-top: 1.5em;">那如果对&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Promise</code>&nbsp;不进行&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">catch</code>&nbsp;呢?<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">7</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">8</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">window</span>.addEventListener(<span class="string" style="color: rgb(24, 54, 145);">"unhandledrejection"</span>, <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span>(<span class="params">e</span>)</span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">e.preventDefault()</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(<span class="string" style="color: rgb(24, 54, 145);">'捕获到异常:'</span>, e);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">return</span> <span class="literal" style="color: rgb(0, 134, 179);">true</span>;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">});</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">new</span> <span class="built_in" style="color: rgb(121, 93, 163);">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">reject(<span class="string" style="color: rgb(24, 54, 145);">'jartto: promise error'</span>);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">});</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><div class="alert info" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(52, 158, 243); border-right: none rgb(52, 158, 243); border-bottom: none rgb(52, 158, 243); border-image: initial; border-left: 3px solid rgb(52, 158, 243); background-color: rgb(230, 243, 254);"><p>嗯,事实证明,也是会被正常捕获到的。</p></div><p style="margin-top: 1.5em;">所以,正如我们上面所说,为了防止有漏掉的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Promise</code>&nbsp;异常,建议在全局增加一个对&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">unhandledrejection</code>&nbsp;的监听,用来全局监听&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Uncaught Promise Error</code>。</p><p style="margin-top: 1.5em;">补充一点:如果去掉控制台的异常显示,需要加上:<br></p><figure class="highlight plain" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">event.preventDefault();</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><h4 id="七、VUE-errorHandler" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#七、VUE-errorHandler" class="headerlink" title="七、VUE errorHandler" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>七、VUE errorHandler</h4><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">Vue.config.errorHandler = <span class="function">(<span class="params">err, vm, info</span>) =&gt;</span> {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.error(<span class="string" style="color: rgb(24, 54, 145);">'通过vue errorHandler捕获的错误'</span>);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.error(err);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.error(vm);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.error(info);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div></pre></td></tr></tbody></table></figure><h4 id="八、React-异常捕获" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#八、React-异常捕获" class="headerlink" title="八、React 异常捕获" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>八、React 异常捕获</h4><p style="margin-top: 1.5em;"><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">React 16</code>&nbsp;提供了一个内置函数&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">componentDidCatch</code>,使用它可以非常简单的获取到&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">react</code>&nbsp;下的错误信息<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">componentDidCatch(error, info) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(error, info);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">除此之外,我们可以了解一下:<a href="https://blog.csdn.net/a986597353/article/details/78469979" target="_blank" rel="external" style="color: rgb(52, 158, 243); text-decoration-line: none;"><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">error boundary</code></a><br><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">UI</code>&nbsp;的某部分引起的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">JS</code>&nbsp;错误不应该破坏整个程序,为了帮&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">React</code>&nbsp;的使用者解决这个问题,<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">React 16</code>&nbsp;介绍了一种关于错误边界(<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">error boundary</code>)的新观念。</p><div class="alert warning" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(245, 170, 10); border-right: none rgb(245, 170, 10); border-bottom: none rgb(245, 170, 10); border-image: initial; border-left: 3px solid rgb(245, 170, 10); background-color: rgb(253, 241, 216);"><p>需要注意的是: error boundaries 并不会捕捉下面这些错误。</p></div><p style="margin-top: 1.5em;">1.事件处理器<br>2.异步代码<br>3.服务端的渲染代码<br>4.在&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">error boundaries</code>&nbsp;区域内的错误</p><p style="margin-top: 1.5em;">我们来举一个小例子,在下面这个&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">componentDIdCatch(error,info)</code>&nbsp;里的类会变成一个&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">error boundary</code>:<br></p><figure class="highlight jsx" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">7</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">8</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">9</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">10</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">11</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">12</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">13</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">14</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">15</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">16</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">17</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">18</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">19</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">20</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">21</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 672px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 672px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="class"><span class="keyword" style="color: rgb(167, 29, 93);">class</span> <span class="title">ErrorBoundary</span> <span class="keyword" style="color: rgb(167, 29, 93);">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">constructor</span>(props) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="keyword" style="color: rgb(167, 29, 93);">super</span>(props);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="keyword" style="color: rgb(167, 29, 93);">this</span>.state = { <span class="attr">hasError</span>: <span class="literal">false</span> };</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"> </div><div class="line" style="height: 1.3em; font-size: 1.4rem;">componentDidCatch(error, info) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="comment" style="color: rgb(150, 152, 150);">// Display fallback UI</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="keyword" style="color: rgb(167, 29, 93);">this</span>.setState({ <span class="attr">hasError</span>: <span class="literal">true</span> });</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="comment" style="color: rgb(150, 152, 150);">// You can also log the error to an error reporting service</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    logErrorToMyService(error, info);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"> </div><div class="line" style="height: 1.3em; font-size: 1.4rem;">render() {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="keyword" style="color: rgb(167, 29, 93);">if</span> (<span class="keyword" style="color: rgb(167, 29, 93);">this</span>.state.hasError) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">      <span class="comment" style="color: rgb(150, 152, 150);">// You can render any custom fallback UI</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;">      <span class="keyword" style="color: rgb(167, 29, 93);">return</span> <span class="xml"><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;<span class="name">h1</span>&gt;</span>Something went wrong.<span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;/<span class="name">h1</span>&gt;</span></span>;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    }</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="keyword" style="color: rgb(167, 29, 93);">return</span> <span class="keyword" style="color: rgb(167, 29, 93);">this</span>.props.children;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">然后我们像使用普通组件那样使用它:<br></p><figure class="highlight plain" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">&lt;ErrorBoundary&gt;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">&lt;MyWidget /&gt;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">&lt;/ErrorBoundary&gt;</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;"><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">componentDidCatch()</code>&nbsp;方法像&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">JS</code>&nbsp;的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">catch{}</code>&nbsp;模块一样工作,但是对于组件,只有&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">class</code>&nbsp;类型的组件(<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">class component</code>&nbsp;)可以成为一个&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">error boundaries</code>&nbsp;。</p><p style="margin-top: 1.5em;">实际上,大多数情况下我们可以在整个程序中定义一个&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">error boundary</code>&nbsp;组件,之后就可以一直使用它了!</p><h4 id="九、iframe-异常" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#九、iframe-异常" class="headerlink" title="九、iframe 异常" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>九、iframe 异常</h4><p style="margin-top: 1.5em;">对于&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">iframe</code>&nbsp;的异常捕获,我们还得借力&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">window.onerror</code>:<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">window</span>.onerror = <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span>(<span class="params">message, source, lineno, colno, error</span>) </span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">console</span>.log(<span class="string" style="color: rgb(24, 54, 145);">'捕获到异常:'</span>,{message, source, lineno, colno, error});</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">一个简单的例子可能如下:<br></p><figure class="highlight html" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">7</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">8</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;<span class="name" style="color: rgb(99, 163, 92);">iframe</span> <span class="attr" style="color: rgb(121, 93, 163);">src</span>=<span class="string" style="color: rgb(24, 54, 145);">"./iframe.html"</span> <span class="attr" style="color: rgb(121, 93, 163);">frameborder</span>=<span class="string" style="color: rgb(24, 54, 145);">"0"</span>&gt;</span><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;/<span class="name" style="color: rgb(99, 163, 92);">iframe</span>&gt;</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;<span class="name" style="color: rgb(99, 163, 92);">script</span>&gt;</span><span class="undefined"></span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="javascript"><span class="built_in">window</span>.frames[<span class="number">0</span>].onerror = <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span> (<span class="params">message, source, lineno, colno, error</span>) </span>{</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="javascript">    <span class="built_in">console</span>.log(<span class="string" style="color: rgb(24, 54, 145);">'捕获到 iframe 异常:'</span>,{message, source, lineno, colno, error});</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="javascript">    <span class="keyword" style="color: rgb(167, 29, 93);">return</span> <span class="literal">true</span>;</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="undefined">};</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="undefined"></span><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;/<span class="name" style="color: rgb(99, 163, 92);">script</span>&gt;</span></div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><h4 id="十、Script-error" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#十、Script-error" class="headerlink" title="十、Script error" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>十、Script error</h4><p style="margin-top: 1.5em;">一般情况,如果出现&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Script error</code>&nbsp;这样的错误,基本上可以确定是出现了跨域问题。这时候,是不会有其他太多辅助信息的,但是解决思路无非如下:</p><div class="alert info" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(52, 158, 243); border-right: none rgb(52, 158, 243); border-bottom: none rgb(52, 158, 243); border-image: initial; border-left: 3px solid rgb(52, 158, 243); background-color: rgb(230, 243, 254);"><p>跨源资源共享机制(&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">CORS</code>&nbsp;):我们为&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">script</code>&nbsp;标签添加&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">crossOrigin</code>&nbsp;属性。</p></div><figure class="highlight html" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;<span class="name" style="color: rgb(99, 163, 92);">script</span> <span class="attr" style="color: rgb(121, 93, 163);">src</span>=<span class="string" style="color: rgb(24, 54, 145);">"http://jartto.wang/main.js"</span> <span class="attr" style="color: rgb(121, 93, 163);">crossorigin</span>&gt;</span><span class="undefined"></span><span class="tag" style="display: inline-block; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: inherit; width: auto; height: auto; border-radius: 3px; letter-spacing: 0.01em; cursor: text; border: none;">&lt;/<span class="name" style="color: rgb(99, 163, 92);">script</span>&gt;</span></div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;">或者动态去添加&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">js</code>&nbsp;脚本:<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">const</span> script = <span class="built_in" style="color: rgb(121, 93, 163);">document</span>.createElement(<span class="string" style="color: rgb(24, 54, 145);">'script'</span>);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">script.crossOrigin = <span class="string" style="color: rgb(24, 54, 145);">'anonymous'</span>;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">script.src = url;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">document</span>.body.appendChild(script);</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><div class="alert warning" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(245, 170, 10); border-right: none rgb(245, 170, 10); border-bottom: none rgb(245, 170, 10); border-image: initial; border-left: 3px solid rgb(245, 170, 10); background-color: rgb(253, 241, 216);"><p>特别注意,服务器端需要设置:Access-Control-Allow-Origin</p></div><p style="margin-top: 1.5em;">此外,我们也可以试试这个-<a href="https://juejin.im/post/5c00a405f265da610e7fd024" target="_blank" rel="external" style="color: rgb(52, 158, 243); text-decoration-line: none;">解决 Script Error 的另类思路</a>:<br></p><figure class="highlight plain" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 672px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 672px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">const originAddEventListener = EventTarget.prototype.addEventListener;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">EventTarget.prototype.addEventListener = function (type, listener, options) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">const wrappedListener = function (...args) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    try {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">      return listener.apply(this, args);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    }</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    catch (err) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">      throw err;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    }</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">return originAddEventListener.call(this, type, wrappedListener, options);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">简单解释一下:</p><ul style="margin-bottom: 0.5em;"><li>改写了&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">EventTarget</code>&nbsp;的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">addEventListener</code>&nbsp;方法;</li><li>对传入的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">listener</code>&nbsp;进行包装,返回包装过的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">listener</code>,对其执行进行&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">try-catch</code>;</li><li>浏览器不会对&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">try-catch</code>&nbsp;起来的异常进行跨域拦截,所以&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">catch</code>&nbsp;到的时候,是有堆栈信息的;</li><li>重新&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">throw</code>&nbsp;出来异常的时候,执行的是同域代码,所以&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">window.onerror</code>&nbsp;捕获的时候不会丢失堆栈信息;</li></ul><p style="margin-top: 1.5em;">利用包装&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">addEventListener</code>,我们还可以达到「扩展堆栈」的效果:<br></p><figure class="highlight plain" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 672px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 672px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">(() =&gt; {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">   const originAddEventListener = EventTarget.prototype.addEventListener;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">   EventTarget.prototype.addEventListener = function (type, listener, options) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">+    // 捕获添加事件时的堆栈</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">+    const addStack = new Error(`Event (${type})`).stack;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">   const wrappedListener = function (...args) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">       try {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">         return listener.apply(this, args);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">       }</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">       catch (err) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">+      // 异常发生时,扩展堆栈</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">+      err.stack += '\n' + addStack;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">         throw err;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">       }</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">   }</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">   return originAddEventListener.call(this, type, wrappedListener, options);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">   }</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"> })();</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><h4 id="十一、崩溃和卡顿" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#十一、崩溃和卡顿" class="headerlink" title="十一、崩溃和卡顿" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>十一、崩溃和卡顿</h4><p style="margin-top: 1.5em;">卡顿也就是网页暂时响应比较慢,&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">JS</code>&nbsp;可能无法及时执行。但崩溃就不一样了,网页都崩溃了,<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">JS</code>都不运行了,还有什么办法可以监控网页的崩溃,并将网页崩溃上报呢?</p><div class="alert info" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(52, 158, 243); border-right: none rgb(52, 158, 243); border-bottom: none rgb(52, 158, 243); border-image: initial; border-left: 3px solid rgb(52, 158, 243); background-color: rgb(230, 243, 254);"><p>崩溃和卡顿也是不可忽视的,也许会导致你的用户流失。</p></div><p style="margin-top: 1.5em;">1.利用&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">window</code>&nbsp;对象的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">load</code>&nbsp;和&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">beforeunload</code>&nbsp;事件实现了网页崩溃的监控。<br>不错的文章,推荐阅读:<a href="http://jasonjl.me/blog/2015/06/21/taking-action-on-browser-crashes/" target="_blank" rel="external" style="color: rgb(52, 158, 243); text-decoration-line: none;">Logging Information on Browser Crashes</a>。<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">7</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">8</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">9</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">10</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">11</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">12</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">13</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">14</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">15</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">16</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">17</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">18</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 672px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 672px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">window</span>.addEventListener(<span class="string" style="color: rgb(24, 54, 145);">'load'</span>, <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span> (<span class="params"></span>) </span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    sessionStorage.setItem(<span class="string" style="color: rgb(24, 54, 145);">'good_exit'</span>, <span class="string" style="color: rgb(24, 54, 145);">'pending'</span>);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    setInterval(<span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span> (<span class="params"></span>) </span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">      sessionStorage.setItem(<span class="string" style="color: rgb(24, 54, 145);">'time_before_crash'</span>, <span class="keyword" style="color: rgb(167, 29, 93);">new</span> <span class="built_in" style="color: rgb(121, 93, 163);">Date</span>().toString());</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    }, <span class="number" style="color: rgb(0, 134, 179);">1000</span>);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">});</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="built_in" style="color: rgb(121, 93, 163);">window</span>.addEventListener(<span class="string" style="color: rgb(24, 54, 145);">'beforeunload'</span>, <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span> (<span class="params"></span>) </span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    sessionStorage.setItem(<span class="string" style="color: rgb(24, 54, 145);">'good_exit'</span>, <span class="string" style="color: rgb(24, 54, 145);">'true'</span>);</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">});</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">if</span>(sessionStorage.getItem(<span class="string" style="color: rgb(24, 54, 145);">'good_exit'</span>) &amp;&amp;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    sessionStorage.getItem(<span class="string" style="color: rgb(24, 54, 145);">'good_exit'</span>) !== <span class="string" style="color: rgb(24, 54, 145);">'true'</span>) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    <span class="comment" style="color: rgb(150, 152, 150);">/*</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">      insert crash logging code here</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">    */</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    alert(<span class="string" style="color: rgb(24, 54, 145);">'Hey, welcome back from your crash, looks like you crashed on: '</span> + sessionStorage.getItem(<span class="string" style="color: rgb(24, 54, 145);">'time_before_crash'</span>));</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">2.基于以下原因,我们可以使用&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Service Worker</code>&nbsp;来实现<a href="https://juejin.im/entry/5be158116fb9a049c6434f4a?utm_source=gold_browser_extension" target="_blank" rel="external" style="color: rgb(52, 158, 243); text-decoration-line: none;">网页崩溃的监控</a>:</p><ul style="margin-bottom: 0.5em;"><li><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Service Worker</code>&nbsp;有自己独立的工作线程,与网页区分开,网页崩溃了,<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Service Worker</code>&nbsp;一般情况下不会崩溃;</li><li><code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Service Worker</code>&nbsp;生命周期一般要比网页还要长,可以用来监控网页的状态;</li><li>网页可以通过&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">navigator.serviceWorker.controller.postMessage API</code>&nbsp;向掌管自己的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">SW</code>&nbsp;发送消息。</li></ul><h4 id="十二、错误上报" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#十二、错误上报" class="headerlink" title="十二、错误上报" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>十二、错误上报</h4><p style="margin-top: 1.5em;">1.通过&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Ajax</code>&nbsp;发送数据<br>因为&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Ajax</code>&nbsp;请求本身也有可能会发生异常,而且有可能会引发跨域问题,一般情况下更推荐使用动态创建&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">img</code>&nbsp;标签的形式进行上报。</p><p style="margin-top: 1.5em;">2.动态创建&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">img</code>&nbsp;标签的形式<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span> <span class="title" style="color: rgb(121, 93, 163);">report</span>(<span class="params">error</span>) </span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">let</span> reportUrl = <span class="string" style="color: rgb(24, 54, 145);">'http://jartto.wang/report'</span>;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">new</span> Image().src = <span class="string" style="color: rgb(24, 54, 145);">`<span class="subst">${reportUrl}</span>?logs=<span class="subst">${error}</span>`</span>;</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><p style="margin-top: 1.5em;">收集异常信息量太多,怎么办?实际中,我们不得不考虑这样一种情况:如果你的网站访问量很大,那么一个必然的错误发送的信息就有很多条,这时候,我们需要设置采集率,从而<a href="https://github.com/happylindz/blog/issues/5" target="_blank" rel="external" style="color: rgb(52, 158, 243); text-decoration-line: none;">减缓服务器的压力</a>:<br></p><figure class="highlight js" style="margin-top: 10px; margin-bottom: 10px; line-height: 1.3em; padding-top: 15px; padding-bottom: 15px; overflow: hidden; background: rgb(247, 248, 248); color: rgb(51, 51, 51);"><table style="width: 750px; background: 0px 0px; border-spacing: 0px; display: block;"><tbody><tr><td class="gutter" style="padding: 0.3em 15px; vertical-align: top; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; font-family: Menlo; border-top: none; border-right-color: rgb(230, 230, 230); border-bottom: none; border-left: none; cursor: text;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text;"><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">1</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">2</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">3</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">4</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">5</div><div class="line" style="height: 1.3em; font-size: 1.4rem; color: rgb(170, 170, 170);">6</div></pre></td><td class="code" style="padding: 0.3em 15px 0.3em 1em; vertical-align: top; background-color: inherit; font-family: Menlo; border-width: initial; border-style: none; border-color: initial; cursor: text; width: 680px;"><pre style="background-color: inherit; font-family: Menlo; border: none; cursor: text; max-width: calc(700px); overflow-x: auto; overflow-y: hidden; width: 680px;"><div class="line" style="height: 1.3em; font-size: 1.4rem;">Reporter.send = <span class="function"><span class="keyword" style="color: rgb(167, 29, 93);">function</span>(<span class="params">data</span>) </span>{</div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="comment" style="color: rgb(150, 152, 150);">// 只采集 30%</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;"><span class="keyword" style="color: rgb(167, 29, 93);">if</span>(<span class="built_in" style="color: rgb(121, 93, 163);">Math</span>.random() &lt; <span class="number" style="color: rgb(0, 134, 179);">0.3</span>) {</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">    send(data)      <span class="comment" style="color: rgb(150, 152, 150);">// 上报错误信息</span></div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div><div class="line" style="height: 1.3em; font-size: 1.4rem;">}</div></pre></td></tr></tbody></table></figure><p style="margin-top: 1.5em;"></p><div class="alert info" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(52, 158, 243); border-right: none rgb(52, 158, 243); border-bottom: none rgb(52, 158, 243); border-image: initial; border-left: 3px solid rgb(52, 158, 243); background-color: rgb(230, 243, 254);"><p>采集率应该通过实际情况来设定,随机数,或者某些用户特征都是不错的选择。</p></div><h4 id="十三、总结" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#十三、总结" class="headerlink" title="十三、总结" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>十三、总结</h4><div class="alert warning" style="position: relative; padding: 10px 15px 10px 55px; min-height: 30px; margin-top: 1em; border-top: none rgb(245, 170, 10); border-right: none rgb(245, 170, 10); border-bottom: none rgb(245, 170, 10); border-image: initial; border-left: 3px solid rgb(245, 170, 10); background-color: rgb(253, 241, 216);"><p>回到我们开头提出的那个问题,如何优雅的处理异常呢?</p></div><p style="margin-top: 1.5em;">1.可疑区域增加&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Try-Catch</code><br>2.全局监控&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">JS</code>&nbsp;异常&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">window.onerror</code><br>3.全局监控静态资源异常&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">window.addEventListener</code><br>4.捕获没有&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Catch</code>&nbsp;的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">Promise</code>&nbsp;异常:<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">unhandledrejection</code><br>5.<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">VUE errorHandler</code>&nbsp;和&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">React componentDidCatch</code><br>6.监控网页崩溃:<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">window</code>&nbsp;对象的&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">load</code>&nbsp;和&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">beforeunload</code><br>7.跨域&nbsp;<code style="font-family: Menlo; font-size: 1.5rem; display: inline-block; padding-right: 10px; padding-left: 10px; background-color: rgb(247, 248, 248);">crossOrigin</code>&nbsp;解决</p><p style="margin-top: 1.5em;">其实很简单,正如<a href="http://jartto.wang/2018/11/20/js-exception-handling/" style="color: rgb(52, 158, 243); text-decoration-line: none;">上文</a>所说:采用组合方案,分类型的去捕获异常,这样基本 80%-90% 的问题都化于无形。</p><h4 id="十四、参考" style="font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: -0.04em; line-height: 1.45em; color: rgb(74, 74, 74); margin-top: 1em; margin-bottom: 0.5em; font-size: 2.1rem;"><a href="http://jartto.wang/2018/11/20/js-exception-handling/#十四、参考" class="headerlink" title="十四、参考" style="color: rgb(52, 158, 243); text-decoration-line: none;"></a>十四、参考</h4><p style="margin-top: 1.5em;"><a href="http://jasonjl.me/blog/2015/06/21/taking-action-on-browser-crashes/" target="_blank" rel="external" style="color: rgb(52, 158, 243); text-decoration-line: none;">Logging Information on Browser Crashes</a><br><a href="https://github.com/happylindz/blog/issues/5" target="_blank" rel="external" style="color: rgb(52, 158, 243); text-decoration-line: none;">前端代码异常监控实战</a><br><a href="https://blog.csdn.net/a986597353/article/details/78469979" target="_blank" rel="external" style="color: rgb(52, 158, 243); text-decoration-line: none;">Error Boundaries</a><br><a href="https://github.com/RicardoCao-Biker/Front-End-Monitoring/blob/master/BasicKnowledge.md" target="_blank" rel="external" style="color: rgb(52, 158, 243); text-decoration-line: none;">前端监控知识点</a><br><a href="https://blog.sentry.io/2016/01/04/client-javascript-reporting-window-onerror" target="_blank" rel="external" style="color: rgb(52, 158, 243); text-decoration-line: none;">Capture and report JavaScript errors with window.onerror</a></p></div></div><div id="post-footer" class="post-footer main-content-wrap" style="max-width: 750px; margin-top: 20px; margin-right: auto; margin-left: auto; padding-right: 20px; padding-left: 20px; color: rgb(0, 0, 0); font-family: &quot;Open Sans&quot;, sans-serif; letter-spacing: 0.16px;"><div style="color: rgb(117, 114, 136); font-size: 1.3rem; padding: 2px 6px; border: 1px solid rgb(250, 210, 210); background: rgb(255, 236, 234); border-radius: 3px; line-height: 22px;">版权声明:<br>文章首发于&nbsp;<a href="http://jartto.wang/" style="color: rgb(52, 158, 243); text-decoration-line: none;">Jartto's blog&nbsp;</a>, 转载文章请务必以超链接形式标明文章出处,作者信息及本版权声明(<a href="http://jartto.wang/" style="color: rgb(52, 158, 243); text-decoration-line: none;">&nbsp;http://jartto.wang&nbsp;</a>)。</div></div>
页: [1]
查看完整版本: 如何优雅处理前端异常?