cainiaoblog 23.2.171
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CNAME +1 -0
- package/MP_verify_o6dHCK5mIkxNpzvZ.txt +1 -0
- package/README.md +8 -0
- package/about/index.html +54 -0
- package/ads.txt +1 -0
- package/app/manual.html +104 -0
- package/appConfigs/config +1 -0
- package/archives/2018/index.html +48 -0
- package/archives/2019/index.html +48 -0
- package/archives/2019/page/2/index.html +48 -0
- package/archives/2020/index.html +48 -0
- package/archives/2021/index.html +48 -0
- package/archives/2022/index.html +48 -0
- package/archives/2023/index.html +48 -0
- package/archives/index.html +48 -0
- package/archives/page/2/index.html +48 -0
- package/archives/page/3/index.html +48 -0
- package/article/10047.html +148 -0
- package/article/10164.html +64 -0
- package/article/10624.html +436 -0
- package/article/10745.html +586 -0
- package/article/11674.html +71 -0
- package/article/11939.html +72 -0
- package/article/12238.html +86 -0
- package/article/1230.html +533 -0
- package/article/13265.html +69 -0
- package/article/13823.html +78 -0
- package/article/14125.html +72 -0
- package/article/14192.html +561 -0
- package/article/14375.html +85 -0
- package/article/14744.html +83 -0
- package/article/14936.html +451 -0
- package/article/1518.html +250 -0
- package/article/15428.html +71 -0
- package/article/15518.html +288 -0
- package/article/15569.html +418 -0
- package/article/1566.html +122 -0
- package/article/16017.html +156 -0
- package/article/16947.html +440 -0
- package/article/17096.html +82 -0
- package/article/17246.html +89 -0
- package/article/17575.html +350 -0
- package/article/179.html +757 -0
- package/article/18039.html +233 -0
- package/article/18071.html +375 -0
- package/article/18142.html +71 -0
- package/article/19909.html +160 -0
- package/article/20014.html +89 -0
- package/article/20021.html +389 -0
- package/article/20037.html +280 -0
- package/article/20056.html +95 -0
- package/article/20093.html +404 -0
- package/article/2021.html +607 -0
- package/article/20459.html +115 -0
- package/article/20613.html +263 -0
- package/article/20635.html +71 -0
- package/article/21317.html +71 -0
- package/article/21320.html +90 -0
- package/article/21782.html +548 -0
- package/article/22230.html +435 -0
- package/article/22237.html +347 -0
- package/article/22398.html +109 -0
- package/article/22422.html +270 -0
- package/article/22565.html +300 -0
- package/article/23046.html +250 -0
- package/article/23083.html +215 -0
- package/article/23195.html +297 -0
- package/article/23301.html +835 -0
- package/article/23589.html +285 -0
- package/article/23655.html +338 -0
- package/article/23864.html +76 -0
- package/article/23914.html +96 -0
- package/article/24169.html +135 -0
- package/article/24581.html +349 -0
- package/article/2475.html +500 -0
- package/article/24826.html +77 -0
- package/article/24924.html +247 -0
- package/article/25164.html +1495 -0
- package/article/25318.html +394 -0
- package/article/25710.html +1129 -0
- package/article/25734.html +83 -0
- package/article/26083.html +174 -0
- package/article/26147.html +283 -0
- package/article/26291.html +110 -0
- package/article/26354.html +71 -0
- package/article/26624.html +145 -0
- package/article/26639.html +298 -0
- package/article/26850.html +138 -0
- package/article/26940.html +258 -0
- package/article/27796.html +190 -0
- package/article/27800.html +161 -0
- package/article/28963.html +159 -0
- package/article/28976.html +247 -0
- package/article/29042.html +72 -0
- package/article/29596.html +81 -0
- package/article/29619.html +183 -0
- package/article/29623.html +329 -0
- package/article/29829.html +205 -0
- package/article/29abbd1c.html +112 -0
- package/article/30215.html +178 -0
- package/article/30552.html +78 -0
- package/article/30818.html +201 -0
- package/article/31330.html +364 -0
- package/article/3154.html +577 -0
- package/article/31695.html +348 -0
- package/article/31826.html +71 -0
- package/article/31843.html +132 -0
- package/article/32280.html +212 -0
- package/article/32431.html +74 -0
- package/article/32443.html +72 -0
- package/article/32732.html +122 -0
- package/article/3286.html +251 -0
- package/article/32960.html +198 -0
- package/article/33713.html +72 -0
- package/article/33899.html +615 -0
- package/article/34351.html +74 -0
- package/article/34372.html +89 -0
- package/article/34410.html +74 -0
- package/article/34431.html +118 -0
- package/article/3447.html +75 -0
- package/article/34474.html +142 -0
- package/article/34871.html +147 -0
- package/article/35397.html +175 -0
- package/article/3544.html +199 -0
- package/article/35503.html +115 -0
- package/article/35624.html +84 -0
- package/article/35697.html +384 -0
- package/article/35863.html +73 -0
- package/article/36037.html +253 -0
- package/article/36118.html +71 -0
- package/article/3621.html +119 -0
- package/article/36251.html +296 -0
- package/article/36642.html +352 -0
- package/article/37102.html +763 -0
- package/article/37336.html +351 -0
- package/article/37351.html +89 -0
- package/article/3760.html +294 -0
- package/article/37749.html +75 -0
- package/article/37789.html +83 -0
- package/article/38005.html +765 -0
- package/article/38009.html +284 -0
- package/article/38269.html +194 -0
- package/article/38344.html +88 -0
- package/article/38359.html +334 -0
- package/article/38423.html +379 -0
- package/article/38530.html +213 -0
- package/article/38743.html +268 -0
- package/article/38753.html +204 -0
- package/article/38881.html +71 -0
- package/article/39087.html +414 -0
- package/article/39309.html +84 -0
- package/article/39486.html +74 -0
- package/article/39637.html +306 -0
- package/article/39839.html +72 -0
- package/article/39937.html +152 -0
- package/article/39970.html +71 -0
- package/article/402.html +559 -0
- package/article/40698.html +71 -0
- package/article/40811.html +71 -0
- package/article/40964.html +462 -0
- package/article/41011.html +322 -0
- package/article/41152.html +78 -0
- package/article/41696.html +71 -0
- package/article/41717.html +281 -0
- package/article/41777.html +149 -0
- package/article/419.html +985 -0
- package/article/4233.html +136 -0
- package/article/4292.html +86 -0
- package/article/43302.html +96 -0
- package/article/43397.html +106 -0
- package/article/43724.html +281 -0
- package/article/43999.html +224 -0
- package/article/44426.html +77 -0
- package/article/44964.html +137 -0
- package/article/45004.html +123 -0
- package/article/4510.html +83 -0
- package/article/45156.html +320 -0
- package/article/45157.html +52 -0
- package/article/45267.html +87 -0
- package/article/45641.html +207 -0
- package/article/45960.html +75 -0
- package/article/46100.html +1262 -0
- package/article/46366.html +74 -0
- package/article/46771.html +96 -0
- package/article/46911.html +517 -0
- package/article/46948.html +137 -0
- package/article/46ee4850.html +349 -0
- package/article/47019.html +84 -0
- package/article/47532.html +94 -0
- package/article/4783.html +429 -0
- package/article/47972.html +72 -0
- package/article/48216.html +127 -0
- package/article/48252.html +185 -0
- package/article/48520.html +74 -0
- package/article/48722.html +75 -0
- package/article/48807.html +99 -0
- package/article/49126.html +323 -0
- package/article/50001.html +88 -0
- package/article/50058.html +151 -0
- package/article/50343.html +410 -0
- package/article/50510.html +82 -0
- package/article/51082.html +98 -0
- package/article/51677.html +111 -0
- package/article/5204.html +1085 -0
- package/article/52500.html +538 -0
- package/article/52689.html +259 -0
- package/article/52877.html +569 -0
- package/article/53125.html +191 -0
- package/article/53428.html +251 -0
- package/article/53524.html +74 -0
- package/article/53698.html +322 -0
- package/article/53803e6.html +93 -0
- package/article/53924.html +291 -0
- package/article/53962.html +253 -0
- package/article/54006.html +71 -0
- package/article/54018.html +88 -0
- package/article/54161.html +83 -0
- package/article/54178.html +69 -0
- package/article/54258.html +327 -0
- package/article/54295.html +214 -0
- package/article/54313.html +1976 -0
- package/article/54351.html +90 -0
- package/article/54604.html +80 -0
- package/article/54632.html +71 -0
- package/article/54912.html +756 -0
- package/article/54918.html +129 -0
- package/article/55119.html +136 -0
- package/article/55756.html +118 -0
- package/article/55769.html +136 -0
- package/article/55870.html +161 -0
- package/article/56139.html +92 -0
- package/article/56557.html +69 -0
- package/article/56604.html +69 -0
- package/article/56816.html +266 -0
- package/article/56926.html +153 -0
- package/article/57747.html +409 -0
- package/article/57965.html +475 -0
- package/article/58816.html +78 -0
- package/article/59059.html +435 -0
- package/article/59095.html +350 -0
- package/article/59349.html +244 -0
- package/article/59402.html +216 -0
- package/article/59448.html +55 -0
- package/article/59870.html +94 -0
- package/article/59877.html +208 -0
- package/article/5dbb6f41.html +86 -0
- package/article/6008.html +75 -0
- package/article/60327.html +126 -0
- package/article/6035.html +76 -0
- package/article/60428.html +71 -0
- package/article/60544.html +128 -0
- package/article/61319.html +95 -0
- package/article/61367.html +93 -0
- package/article/624d1918.html +292 -0
- package/article/62543.html +71 -0
- package/article/62887.html +169 -0
- package/article/63074.html +120 -0
- package/article/63266.html +311 -0
- package/article/63351.html +74 -0
- package/article/63542.html +104 -0
- package/article/63824.html +275 -0
- package/article/64051.html +653 -0
- package/article/64189b69.html +72 -0
- package/article/64354.html +75 -0
- package/article/64869.html +79 -0
- package/article/64923.html +596 -0
- package/article/65128.html +95 -0
- package/article/65295.html +79 -0
- package/article/6888.html +75 -0
- package/article/7065.html +84 -0
- package/article/7455.html +85 -0
- package/article/7a3ef8f.html +315 -0
- package/article/8140.html +188 -0
- package/article/8190.html +85 -0
- package/article/8225.html +78 -0
- package/article/84c9ccd6.html +159 -0
- package/article/8f9a9ae3.html +82 -0
- package/article/9174.html +73 -0
- package/article/9738.html +294 -0
- package/article/a4145266.html +71 -0
- package/article/bedea419.html +72 -0
- package/article/bf7e7421.html +78 -0
- package/article/c1867fbf.html +103 -0
- package/article/c5576490.html +70 -0
- package/article/dcb0db28.html +76 -0
- package/article/fc3b727a.html +79 -0
- package/atom.xml +445 -0
- package/baidusitemap.xml +1079 -0
- package/blocks/dns.txt +264 -0
- package/blocks/filter.txt +1070 -0
- package/blocks/script.js +42 -0
- package/categories/CDN/index.html +48 -0
- package/categories/IDE/index.html +48 -0
- package/categories/git/index.html +48 -0
- package/categories/hexo/index.html +48 -0
- package/categories//345/205/254/345/205/261/350/212/202/346/227/245/index.html +48 -0
- package/categories//345/210/206/344/272/253/index.html +48 -0
- package/categories//345/211/215/347/253/257/index.html +48 -0
- package/categories//345/211/215/347/253/257/page/2/index.html +48 -0
- package/categories//345/211/215/347/253/257//346/265/217/350/247/210/345/231/250/index.html +48 -0
- package/categories//345/211/215/347/253/257//346/265/217/350/247/210/345/231/250//347/275/221/347/273/234/345/215/217/350/256/256/index.html +48 -0
- package/categories//345/215/232/345/256/242/index.html +48 -0
- package/categories//345/267/245/345/205/267/index.html +48 -0
- package/categories//345/271/277/345/221/212/350/277/207/346/273/244/index.html +48 -0
- package/categories//345/271/277/345/221/212/350/277/207/346/273/244//350/247/206/351/242/221/347/224/265/350/247/206/345/260/217/350/257/264/346/274/253/347/224/273/350/265/204/350/256/257/351/237/263/344/271/220/index.html +48 -0
- package/categories//346/255/243/345/210/231/index.html +48 -0
- package/categories//346/265/217/350/247/210/345/231/250/index.html +48 -0
- package/categories//347/256/227/346/263/225/index.html +48 -0
- package/categories//350/265/204/350/256/257/index.html +48 -0
- package/categories//350/275/273/346/235/276/344/270/200/345/210/273/index.html +48 -0
- package/cdn/css/font-awesome.min.css +4 -0
- package/cdn/css/grids-responsive-min.css +7 -0
- package/cdn/css/normalize.css +349 -0
- package/cdn/css/pure-min.css +11 -0
- package/cdn/fonts/fontawesome-webfont.eot +0 -0
- package/cdn/fonts/fontawesome-webfont.svg +2671 -0
- package/cdn/fonts/fontawesome-webfont.ttf +0 -0
- package/cdn/fonts/fontawesome-webfont.woff +0 -0
- package/cdn/fonts/fontawesome-webfont.woff2 +0 -0
- package/cdn/js/Valine.min.js +17 -0
- package/cdn/js/canvas-nest.js +1 -0
- package/cdn/js/clipboard.min.js +7 -0
- package/cdn/js/crypto-js.js +25 -0
- package/cdn/js/jquery.min.js +2 -0
- package/css/default.css +1144 -0
- package/css/donate.css +338 -0
- package/css/hbe.style.css +749 -0
- package/css/style.css +2095 -0
- package/donate/index.html +39 -0
- package/google917dcf72f6e5c7f5.html +1 -0
- package/guestbook/index.html +68 -0
- package/hosts/ads.txt +149 -0
- package/hosts/flash.txt +9 -0
- package/hosts/github.txt +6 -0
- package/hosts/google.txt +16936 -0
- package/hosts/winrar.txt +2 -0
- package/img/alipay.svg +46 -0
- package/img/bitcoin.svg +135 -0
- package/img/blog.ico +0 -0
- package/img/blog.png +0 -0
- package/img/gaba.png +0 -0
- package/img/github.svg +1 -0
- package/img/like.svg +1 -0
- package/img/mp-mini.jpg +0 -0
- package/img/mp.png +0 -0
- package/img/paypal.svg +63 -0
- package/img/upy_logo.svg +59 -0
- package/img/wechat.svg +49 -0
- package/index.html +48 -0
- package/jd_root.txt +1 -0
- package/js/codeblock-resizer.js +51 -0
- package/js/dark.js +12 -0
- package/js/donate.js +87 -0
- package/js/fixedPage.js +106 -0
- package/js/gitment.browser.js +3751 -0
- package/js/search.js +86 -0
- package/js/share.js +60 -0
- package/js/smartresize.js +32 -0
- package/js/totop.js +12 -0
- package/kankan/index.html +77 -0
- package/lib/hbe.js +293 -0
- package/package.json +25 -0
- package/page/10/index.html +49 -0
- package/page/11/index.html +59 -0
- package/page/12/index.html +67 -0
- package/page/13/index.html +63 -0
- package/page/14/index.html +66 -0
- package/page/15/index.html +60 -0
- package/page/16/index.html +60 -0
- package/page/17/index.html +62 -0
- package/page/18/index.html +61 -0
- package/page/19/index.html +58 -0
- package/page/2/index.html +48 -0
- package/page/20/index.html +57 -0
- package/page/21/index.html +61 -0
- package/page/22/index.html +55 -0
- package/page/23/index.html +64 -0
- package/page/24/index.html +60 -0
- package/page/25/index.html +58 -0
- package/page/26/index.html +48 -0
- package/page/27/index.html +58 -0
- package/page/3/index.html +48 -0
- package/page/4/index.html +48 -0
- package/page/5/index.html +51 -0
- package/page/6/index.html +51 -0
- package/page/7/index.html +51 -0
- package/page/8/index.html +53 -0
- package/page/9/index.html +48 -0
- package/randomcall/README.html +1 -0
- package/randomcall/lucker.html +290 -0
- package/randomcall/lucky.png +0 -0
- package/robots.txt +22 -0
- package/search.xml +6740 -0
- package/sitemap.xml +2669 -0
- package/tags//345/216/237/345/210/233/index.html +48 -0
- package/tags//345/250/261/344/271/220/index.html +48 -0
- package/tags//346/211/213/345/206/231/index.html +48 -0
- package/tags//347/226/253/346/203/205/index.html +48 -0
- package/tags//350/275/254/350/275/275/index.html +48 -0
- package/tags//350/275/254/350/275/275/page/2/index.html +48 -0
- package/v.html +90 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
<!DOCTYPE html><html lang="zh-CN" data-dark><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"><meta content="yes" name="apple-mobile-web-app-capable"><meta content="black-translucent" name="apple-mobile-web-app-status-bar-style"><meta content="telephone=no" name="format-detection"><meta name="description" content="前端壹菜鸟,记录工作难题,关注前端知识,收集精彩博文,做技术的搬运工"><meta name="msvalidate.01" content="0FE4D8B3381D3D87088996B886E1E2BD"><title>如何优雅处理前端异常? | 前端壹菜鸟</title><link rel="stylesheet" type="text/css" href="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/css/style.min.css"><link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/normalize.css@latest/normalize.min.css"><link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/purecss@latest/build/pure-min.min.css"><link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/purecss@latest/build/grids-responsive-min.css"><link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css"><link rel="icon" mask="" sizes="any" href="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/img/blog.ico"><link rel="Shortcut Icon" type="image/x-icon" href="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/img/blog.ico"><link rel="apple-touch-icon" href="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/img/blog.png"><link rel="apple-touch-icon-precomposed" href="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/img/blog.png"><link rel="alternate" type="application/atom+xml" href="/atom.xml"><script type="text/javascript" src="//cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js"></script><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8385136408348258"></script><script src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async></script><script>(function(){
|
|
2
|
+
var bp = document.createElement('script');
|
|
3
|
+
var curProtocol = window.location.protocol.split(':')[0];
|
|
4
|
+
if (curProtocol === 'https'){
|
|
5
|
+
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
|
|
6
|
+
}
|
|
7
|
+
else{
|
|
8
|
+
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
|
|
9
|
+
}
|
|
10
|
+
var s = document.getElementsByTagName("script")[0];
|
|
11
|
+
s.parentNode.insertBefore(bp, s);
|
|
12
|
+
})();
|
|
13
|
+
</script><script>(function(){
|
|
14
|
+
var src = 'https://jspassport.ssl.qhimg.com/11.0.1.js?d182b3f28525f2db83acfaaf6e696dba';
|
|
15
|
+
document.write('<script src="' + src + '" id="sozz"><\/script>');
|
|
16
|
+
})();
|
|
17
|
+
</script><script>var _hmt=_hmt||[];(function(){var hm=document.createElement("script");hm.src='https://hm.baidu.com/hm.js?011f0b44e8452bfa57fbfa23c5fe7683';var s=document.getElementsByTagName("script")[0];s.parentNode.insertBefore(hm, s);})();
|
|
18
|
+
</script><script async src="https://www.googletagmanager.com/gtag/js?id=UA-150860401-1"></script><script>window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);};gtag('js',new Date());gtag('config','UA-150860401-1');
|
|
19
|
+
</script><script type="text/javascript" src="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/js/fixedPage.min.js"></script><meta name="generator" content="Hexo 6.3.0"></head><body><div class="body_container"><div id="header"><div class="site-name"><a id="logo" href="/.">前端壹菜鸟</a><p class="description">关注前端知识,收集精彩博文,做技术的搬运工</p></div><div id="nav-menu"><a class="current" href="/." target="_self"><i class="fa fa-home"> 首页</i></a><a href="/archives/" target="_self"><i class="fa fa-archive"> 归档</i></a><a href="/guestbook/" target="_self"><i class="fa fa-comments"> 留言</i></a><a href="/about/" target="_self"><i class="fa fa-user"> 关于</i></a><a href="https://laonongmin.online/" target="_target"><i class="fa fa-group"> 看看</i></a><a href="https://love.xuehuayu.cn/" target="_target"><i class="fa fa-heart"> LOVE</i></a></div></div><div class="pure-g" id="layout"><div class="pure-u-1 pure-u-md-3-4"><div class="content_container"><div class="post"><h1 class="post-title c-post">如何优雅处理前端异常?</h1><div class="post-meta"><span class="date">2020-01-13</span><span> | </span><span class="tag"><a href="/tags/%E8%BD%AC%E8%BD%BD/">转载 </a></span><span> | </span><span class="category"><a href="/categories/%E5%89%8D%E7%AB%AF/">前端 </a></span><span id="busuanzi_container_page_pv"> | <span id="busuanzi_value_page_pv"><i class="fa fa-spinner"></i></span><span> 阅读</span></span><span class="post-time"><span class="post-meta-item-text"> | </span><span class="post-meta-item-icon"><i class="fa fa-keyboard-o"></i><span class="post-count"> 3.5k</span><span class="post-meta-item-text"> 字</span></span></span><span class="post-time"> | <span class="post-meta-item-icon"><i class="fa fa-hourglass-half"></i><span class="post-count"> 14</span><span class="post-meta-item-text"> 分钟</span></span></span></div><a class="disqus-comment-count" href="/article/18039.html#vcomment"><span class="waline-comment-count" data-path="/article/18039.html"></span><span> 条评论</span></a><div class="post-content"><p><code>作者: Jartto's blog 原文地址:http://jartto.wang/2018/11/20/js-exception-handling/</code></p>
|
|
20
|
+
<p>前端一直是距离用户最近的一层,随着产品的日益完善,我们会更加注重用户体验,而前端异常却如鲠在喉,甚是烦人。</p>
|
|
21
|
+
<span id="more"></span>
|
|
22
|
+
|
|
23
|
+
<h4 id="一、为什么要处理异常?"><a href="#一、为什么要处理异常?" class="headerlink" title="一、为什么要处理异常?"></a>一、为什么要处理异常?</h4><p>异常是不可控的,会影响最终的呈现结果,但是我们有充分的理由去做这样的事情。</p>
|
|
24
|
+
<p>1.增强用户体验;<br>2.远程定位问题;<br>3.未雨绸缪,及早发现问题;<br>4.无法复线问题,尤其是移动端,机型,系统都是问题;<br>5.完善的前端方案,前端监控系统;</p>
|
|
25
|
+
<p>对于 <code>JS</code> 而言,我们面对的仅仅只是异常,异常的出现不会直接导致 <code>JS</code> 引擎崩溃,最多只会使当前执行的任务终止。</p>
|
|
26
|
+
<h4 id="二、需要处理哪些异常?"><a href="#二、需要处理哪些异常?" class="headerlink" title="二、需要处理哪些异常?"></a>二、需要处理哪些异常?</h4><p>对于前端来说,我们可做的异常捕获还真不少。总结一下,大概如下:</p>
|
|
27
|
+
<ul>
|
|
28
|
+
<li><code>JS</code> 语法错误、代码异常</li>
|
|
29
|
+
<li><code>AJAX</code> 请求异常</li>
|
|
30
|
+
<li>静态资源加载异常</li>
|
|
31
|
+
<li><code>Promise</code> 异常</li>
|
|
32
|
+
<li><code>Iframe</code> 异常</li>
|
|
33
|
+
<li>跨域 Script error </li>
|
|
34
|
+
<li>崩溃和卡顿</li>
|
|
35
|
+
</ul>
|
|
36
|
+
<p><a target="_blank" rel="noopener" href="http://jartto.wang/2018/11/20/js-exception-handling/">下面</a>我会针对每种具体情况来说明如何处理这些异常。</p>
|
|
37
|
+
<h4 id="三、Try-Catch-的误区"><a href="#三、Try-Catch-的误区" class="headerlink" title="三、Try-Catch 的误区"></a>三、Try-Catch 的误区</h4><p><code>try-catch</code> 只能捕获到同步的运行时错误,对语法和异步错误却无能为力,捕获不到。<br>1.同步运行时错误:</p>
|
|
38
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">let</span> name = <span class="string">'jartto'</span>;</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(nam);</span><br><span class="line">} <span class="keyword">catch</span>(e) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到异常:'</span>,e);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
|
39
|
+
|
|
40
|
+
<p>输出:</p>
|
|
41
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">捕获到异常: <span class="title class_">ReferenceError</span>: nam is not defined</span><br><span class="line"> at <anonymous>:<span class="number">3</span>:<span class="number">15</span></span><br></pre></td></tr></table></figure>
|
|
42
|
+
|
|
43
|
+
<p>2.不能捕获到语法错误,我们修改一下代码,删掉一个单引号:</p>
|
|
44
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">let</span> name = <span class="string">'jartto;</span></span><br><span class="line"><span class="string"> console.log(nam);</span></span><br><span class="line"><span class="string">} catch(e) {</span></span><br><span class="line"><span class="string"> console.log('</span>捕获到异常:<span class="string">',e);</span></span><br><span class="line"><span class="string">}</span></span><br></pre></td></tr></table></figure>
|
|
45
|
+
|
|
46
|
+
<p>输出:</p>
|
|
47
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Uncaught</span> <span class="title class_">SyntaxError</span>: <span class="title class_">Invalid</span> or unexpected token</span><br></pre></td></tr></table></figure>
|
|
48
|
+
|
|
49
|
+
<p>不过语法错误在我们开发阶段就可以看到,应该不会顺利上到线上环境。</p>
|
|
50
|
+
<p>3.异步错误</p>
|
|
51
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> {</span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function">() =></span> {</span><br><span class="line"> <span class="literal">undefined</span>.<span class="title function_">map</span>(<span class="function"><span class="params">v</span> =></span> v);</span><br><span class="line"> }, <span class="number">1000</span>)</span><br><span class="line">} <span class="keyword">catch</span>(e) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到异常:'</span>,e);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
|
52
|
+
|
|
53
|
+
<p>我们看看日志:</p>
|
|
54
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Uncaught</span> <span class="title class_">TypeError</span>: <span class="title class_">Cannot</span> read property <span class="string">'map'</span> <span class="keyword">of</span> <span class="literal">undefined</span></span><br><span class="line"> at <span class="built_in">setTimeout</span> (<anonymous>:<span class="number">3</span>:<span class="number">11</span>)</span><br></pre></td></tr></table></figure>
|
|
55
|
+
|
|
56
|
+
<p>并没有捕获到异常,这是需要我们特别注意的地方。</p>
|
|
57
|
+
<h4 id="四、window-onerror-不是万能的"><a href="#四、window-onerror-不是万能的" class="headerlink" title="四、window.onerror 不是万能的"></a>四、window.onerror 不是万能的</h4><p>当 <code>JS</code> 运行时错误发生时,<code>window</code> 会触发一个 <code>ErrorEvent</code> 接口的 <code>error</code> 事件,并执行 <code>window.onerror()</code>。</p>
|
|
58
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> {<span class="type">String</span>} message 错误信息</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> {<span class="type">String</span>} source 出错文件</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> {<span class="type">Number</span>} lineno 行号</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> {<span class="type">Number</span>} colno 列号</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> {<span class="type">Object</span>} error Error对象(对象)</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">onerror</span> = <span class="keyword">function</span>(<span class="params">message, source, lineno, colno, error</span>) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到异常:'</span>,{message, source, lineno, colno, error});</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
|
59
|
+
|
|
60
|
+
<p>1.首先试试同步运行时错误</p>
|
|
61
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">onerror</span> = <span class="keyword">function</span>(<span class="params">message, source, lineno, colno, error</span>) {</span><br><span class="line"><span class="comment">// message:错误信息(字符串)。</span></span><br><span class="line"><span class="comment">// source:发生错误的脚本URL(字符串)</span></span><br><span class="line"><span class="comment">// lineno:发生错误的行号(数字)</span></span><br><span class="line"><span class="comment">// colno:发生错误的列号(数字)</span></span><br><span class="line"><span class="comment">// error:Error对象(对象)</span></span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到异常:'</span>,{message, source, lineno, colno, error});</span><br><span class="line">}</span><br><span class="line"><span class="title class_">Jartto</span>;</span><br></pre></td></tr></table></figure>
|
|
62
|
+
|
|
63
|
+
<p>可以看到,我们捕获到了异常:<br><img src="https://raw.githubusercontent.com/chenfengyanyu/my-web-accumulation/master/images/js-exception/error1.png" alt="error1"></p>
|
|
64
|
+
<p>2.再试试语法错误呢?</p>
|
|
65
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">onerror</span> = <span class="keyword">function</span>(<span class="params">message, source, lineno, colno, error</span>) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到异常:'</span>,{message, source, lineno, colno, error});</span><br><span class="line">}</span><br><span class="line"><span class="keyword">let</span> name = <span class="string">'Jartto</span></span><br></pre></td></tr></table></figure>
|
|
66
|
+
|
|
67
|
+
<p>控制台打印出了这样的异常:</p>
|
|
68
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Uncaught</span> <span class="title class_">SyntaxError</span>: <span class="title class_">Invalid</span> or unexpected token</span><br></pre></td></tr></table></figure>
|
|
69
|
+
|
|
70
|
+
<p>什么,竟然没有捕获到语法错误?</p>
|
|
71
|
+
<p>3.怀着忐忑的心,我们最后来试试异步运行时错误:</p>
|
|
72
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">onerror</span> = <span class="keyword">function</span>(<span class="params">message, source, lineno, colno, error</span>) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到异常:'</span>,{message, source, lineno, colno, error});</span><br><span class="line">}</span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function">() =></span> {</span><br><span class="line"> <span class="title class_">Jartto</span>;</span><br><span class="line">});</span><br></pre></td></tr></table></figure>
|
|
73
|
+
|
|
74
|
+
<p>控制台输出了:</p>
|
|
75
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">捕获到异常: {<span class="attr">message</span>: <span class="string">"Uncaught ReferenceError: Jartto is not defined"</span>, <span class="attr">source</span>: <span class="string">"http://127.0.0.1:8001/"</span>, <span class="attr">lineno</span>: <span class="number">36</span>, <span class="attr">colno</span>: <span class="number">5</span>, <span class="attr">error</span>: <span class="title class_">ReferenceError</span>: <span class="title class_">Jartto</span> is not defined</span><br><span class="line"> at <span class="built_in">setTimeout</span> (<span class="attr">http</span>:<span class="comment">//127.0.0.1:8001/:36:5)}</span></span><br></pre></td></tr></table></figure>
|
|
76
|
+
|
|
77
|
+
<p>4.接着,我们试试网络请求异常的情况:</p>
|
|
78
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><script></span><br><span class="line"> <span class="variable language_">window</span>.<span class="property">onerror</span> = <span class="keyword">function</span>(<span class="params">message, source, lineno, colno, error</span>) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到异常:'</span>,{message, source, lineno, colno, error});</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"></script></span><br><span class="line"><span class="language-xml"><imgsrc="./jartto.png"></span></span><br></pre></td></tr></table></figure>
|
|
79
|
+
|
|
80
|
+
<p>我们发现,不论是静态资源异常,或者接口异常,错误都无法捕获到。</p>
|
|
81
|
+
<p>补充一点:<code>window.onerror</code> 函数只有在返回 <code>true</code> 的时候,异常才不会向上抛出,否则即使是知道异常的发生控制台还是会显示 <code>Uncaught Error: xxxxx</code></p>
|
|
82
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">onerror</span> = <span class="keyword">function</span>(<span class="params">message, source, lineno, colno, error</span>) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到异常:'</span>,{message, source, lineno, colno, error});</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">}</span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function">() =></span> {</span><br><span class="line"> <span class="title class_">Jartto</span>;</span><br><span class="line">});</span><br></pre></td></tr></table></figure>
|
|
83
|
+
|
|
84
|
+
<p>控制台就不会再有这样的错误了:</p>
|
|
85
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Uncaught</span> <span class="title class_">ReferenceError</span>: <span class="title class_">Jartto</span> is not defined</span><br><span class="line"> at <span class="built_in">setTimeout</span> ((index):<span class="number">36</span>)</span><br></pre></td></tr></table></figure>
|
|
86
|
+
|
|
87
|
+
<p>需要注意:<br><code>onerror</code> 最好写在所有 <code>JS</code> 脚本的前面,否则有可能捕获不到错误;<br><code>onerror</code> 无法捕获语法错误;</p>
|
|
88
|
+
<p>到这里基本就清晰了:在实际的使用过程中,<code>onerror</code> 主要是来捕获预料之外的错误,而 <code>try-catch</code> 则是用来在可预见情况下监控特定的错误,两者结合使用更加高效。</p>
|
|
89
|
+
<p>问题又来了,捕获不到静态资源加载异常怎么办?</p>
|
|
90
|
+
<h4 id="五、window-addEventListener"><a href="#五、window-addEventListener" class="headerlink" title="五、window.addEventListener"></a>五、window.addEventListener</h4><p>当一项资源(如图片或脚本)加载失败,加载资源的元素会触发一个 <code>Event</code> 接口的 <code>error</code> 事件,并执行该元素上的<code>onerror()</code> 处理函数。这些 <code>error</code> 事件不会向上冒泡到 <code>window</code> ,不过(至少在 <code>Firefox</code> 中)能被单一的<code>window.addEventListener</code> 捕获。</p>
|
|
91
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><scritp></span><br><span class="line"> <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">'error'</span>, <span class="function">(<span class="params">error</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到异常:'</span>, error);</span><br><span class="line"> }, <span class="literal">true</span>)</span><br><span class="line"></script></span><br><span class="line"><span class="language-xml"><imgsrc="./jartto.png"></span></span><br></pre></td></tr></table></figure>
|
|
92
|
+
|
|
93
|
+
<p>控制台输出:</p>
|
|
94
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"></span></span><br></pre></td></tr></table></figure>
|
|
95
|
+
|
|
96
|
+
<p>由于网络请求异常不会事件冒泡,因此必须在捕获阶段将其捕捉到才行,但是这种方式虽然可以捕捉到网络请求的异常,但是无法判断 <code>HTTP</code> 的状态是 <code>404</code> 还是其他比如 <code>500</code> 等等,所以还需要配合服务端日志才进行排查分析才可以。</p>
|
|
97
|
+
<p>需要注意:</p>
|
|
98
|
+
<ul>
|
|
99
|
+
<li>不同浏览器下返回的 <code>error</code> 对象可能不同,需要注意兼容处理。</li>
|
|
100
|
+
<li>需要注意避免 <code>addEventListener</code> 重复监听。</li>
|
|
101
|
+
</ul>
|
|
102
|
+
<h4 id="六、Promise-Catch"><a href="#六、Promise-Catch" class="headerlink" title="六、Promise Catch"></a>六、Promise Catch</h4><p>在 <code>promise</code> 中使用 <code>catch</code> 可以非常方便的捕获到异步 <code>error</code> ,这个很简单。</p>
|
|
103
|
+
<p>没有写 <code>catch</code> 的 <code>Promise</code> 中抛出的错误无法被 <code>onerror</code> 或 <code>try-catch</code> 捕获到,所以我们务必要在 <code>Promise</code> 中不要忘记写 <code>catch</code> 处理抛出的异常。</p>
|
|
104
|
+
<p>解决方案: 为了防止有漏掉的 <code>Promise</code> 异常,建议在全局增加一个对 <code>unhandledrejection</code> 的监听,用来全局监听<code>Uncaught Promise Error</code>。使用方式:</p>
|
|
105
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">"unhandledrejection"</span>, <span class="keyword">function</span>(<span class="params">e</span>){</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(e);</span><br><span class="line">});</span><br></pre></td></tr></table></figure>
|
|
106
|
+
|
|
107
|
+
<p>我们继续来尝试一下:</p>
|
|
108
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">"unhandledrejection"</span>, <span class="keyword">function</span>(<span class="params">e</span>){</span><br><span class="line"> e.<span class="title function_">preventDefault</span>()</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到异常:'</span>, e);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">});</span><br><span class="line"><span class="title class_">Promise</span>.<span class="title function_">reject</span>(<span class="string">'promise error'</span>);</span><br></pre></td></tr></table></figure>
|
|
109
|
+
|
|
110
|
+
<p>可以看到如下输出:<br><img src="https://raw.githubusercontent.com/chenfengyanyu/my-web-accumulation/master/images/js-exception/promise.png" alt="promise"></p>
|
|
111
|
+
<p>那如果对 <code>Promise</code> 不进行 <code>catch</code> 呢?</p>
|
|
112
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">"unhandledrejection"</span>, <span class="keyword">function</span>(<span class="params">e</span>){</span><br><span class="line"> e.<span class="title function_">preventDefault</span>()</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到异常:'</span>, e);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">});</span><br><span class="line"><span class="title function_">newPromise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"> <span class="title function_">reject</span>(<span class="string">'jartto: promise error'</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure>
|
|
113
|
+
|
|
114
|
+
<p>嗯,事实证明,也是会被正常捕获到的。</p>
|
|
115
|
+
<p>所以,正如我们上面所说,为了防止有漏掉的 <code>Promise</code> 异常,建议在全局增加一个对 <code>unhandledrejection</code> 的监听,用来全局监听 <code>Uncaught Promise Error</code>。</p>
|
|
116
|
+
<p>补充一点:如果去掉控制台的异常显示,需要加上:</p>
|
|
117
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">event.<span class="title function_">preventDefault</span>();</span><br></pre></td></tr></table></figure>
|
|
118
|
+
|
|
119
|
+
<h4 id="七、VUE-errorHandler"><a href="#七、VUE-errorHandler" class="headerlink" title="七、VUE errorHandler"></a>七、VUE errorHandler</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="property">config</span>.<span class="property">errorHandler</span> = <span class="function">(<span class="params">err, vm, info</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">'通过vue errorHandler捕获的错误'</span>);</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">error</span>(err);</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">error</span>(vm);</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">error</span>(info);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
|
120
|
+
<h4 id="八、React-异常捕获"><a href="#八、React-异常捕获" class="headerlink" title="八、React 异常捕获"></a>八、React 异常捕获</h4><p><code>React 16</code> 提供了一个内置函数 <code>componentDidCatch</code>,使用它可以非常简单的获取到 <code>react</code> 下的错误信息</p>
|
|
121
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">componentDidCatch</span>(<span class="params">error, info</span>) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(error, info);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
|
122
|
+
|
|
123
|
+
<p>除此之外,我们可以了解一下:<a target="_blank" rel="noopener" href="https://blog.csdn.net/a986597353/article/details/78469979"><code>error boundary</code></a><br><code>UI</code> 的某部分引起的 <code>JS</code> 错误不应该破坏整个程序,为了帮 <code>React</code> 的使用者解决这个问题,<code>React 16</code> 介绍了一种关于错误边界(<code>error boundary</code>)的新观念。</p>
|
|
124
|
+
<p>需要注意的是: error boundaries 并不会捕捉下面这些错误。</p>
|
|
125
|
+
<p>1.事件处理器<br>2.异步代码<br>3.服务端的渲染代码<br>4.在 <code>error boundaries</code> 区域内的错误</p>
|
|
126
|
+
<p>我们来举一个小例子,在下面这个 <code>componentDIdCatch(error,info)</code> 里的类会变成一个 <code>error boundary</code>:</p>
|
|
127
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">classErrorBoundaryextendsReact.<span class="property">Component</span>{</span><br><span class="line"> <span class="title function_">constructor</span>(<span class="params">props</span>) {</span><br><span class="line"> <span class="variable language_">super</span>(props);</span><br><span class="line"> <span class="variable language_">this</span>.<span class="property">state</span> = { <span class="attr">hasError</span>: <span class="literal">false</span> };</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="title function_">componentDidCatch</span>(<span class="params">error, info</span>) {</span><br><span class="line"> <span class="comment">// Display fallback UI</span></span><br><span class="line"> <span class="variable language_">this</span>.<span class="title function_">setState</span>({ <span class="attr">hasError</span>: <span class="literal">true</span> });</span><br><span class="line"> <span class="comment">// You can also log the error to an error reporting service</span></span><br><span class="line"> <span class="title function_">logErrorToMyService</span>(error, info);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="title function_">render</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">hasError</span>) {</span><br><span class="line"> <span class="comment">// You can render any custom fallback UI</span></span><br><span class="line"> <span class="keyword">return</span><span class="language-xml"><span class="tag"><<span class="name">h1</span>></span>Something went wrong.<span class="tag"></<span class="name">h1</span>></span></span>;</span><br><span class="line"> }</span><br><span class="line"> returnthis.<span class="property">props</span>.<span class="property">children</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
|
128
|
+
|
|
129
|
+
<p>然后我们像使用普通组件那样使用它:</p>
|
|
130
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><<span class="title class_">ErrorBoundary</span>></span><br><span class="line"> <span class="language-xml"><span class="tag"><<span class="name">MyWidget</span> /></span></span></span><br><span class="line"></<span class="title class_">ErrorBoundary</span>></span><br></pre></td></tr></table></figure>
|
|
131
|
+
|
|
132
|
+
<p><code>componentDidCatch()</code> 方法像 <code>JS</code> 的 <code>catch{}</code> 模块一样工作,但是对于组件,只有 <code>class</code> 类型的组件(<code>class component</code> )可以成为一个 <code>error boundaries</code> 。</p>
|
|
133
|
+
<p>实际上,大多数情况下我们可以在整个程序中定义一个 <code>error boundary</code> 组件,之后就可以一直使用它了!</p>
|
|
134
|
+
<h4 id="九、iframe-异常"><a href="#九、iframe-异常" class="headerlink" title="九、iframe 异常"></a>九、iframe 异常</h4><p>对于 <code>iframe</code> 的异常捕获,我们还得借力 <code>window.onerror</code>:</p>
|
|
135
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">onerror</span> = <span class="keyword">function</span>(<span class="params">message, source, lineno, colno, error</span>) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到异常:'</span>,{message, source, lineno, colno, error});</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
|
136
|
+
|
|
137
|
+
<p>一个简单的例子可能如下:</p>
|
|
138
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><iframesrc=<span class="string">"./iframe.html"</span>frameborder=<span class="string">"0"</span>></iframe></span><br><span class="line"><span class="language-xml"><span class="tag"><<span class="name">script</span>></span><span class="language-javascript"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="variable language_">window</span>.<span class="property">frames</span>[<span class="number">0</span>].<span class="property">onerror</span> = <span class="keyword">function</span> (<span class="params">message, source, lineno, colno, error</span>) {</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">'捕获到 iframe 异常:'</span>,{message, source, lineno, colno, error});</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> <span class="keyword">return</span> <span class="literal">true</span>;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"> };</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span><span class="tag"></<span class="name">script</span>></span></span></span><br></pre></td></tr></table></figure>
|
|
139
|
+
|
|
140
|
+
<h4 id="十、Script-error"><a href="#十、Script-error" class="headerlink" title="十、Script error"></a>十、Script error</h4><p>一般情况,如果出现 <code>Script error</code> 这样的错误,基本上可以确定是出现了跨域问题。这时候,是不会有其他太多辅助信息的,但是解决思路无非如下:</p>
|
|
141
|
+
<p>跨源资源共享机制( <code>CORS</code> ):我们为 <code>script</code> 标签添加 <code>crossOrigin</code> 属性。</p>
|
|
142
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><scriptsrc=<span class="string">"http://jartto.wang/main.js"</span>crossorigin></script></span><br></pre></td></tr></table></figure>
|
|
143
|
+
|
|
144
|
+
<p>或者动态去添加 <code>js</code> 脚本:</p>
|
|
145
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">const</span> script = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">'script'</span>);</span><br><span class="line">script.<span class="property">crossOrigin</span> = <span class="string">'anonymous'</span>;</span><br><span class="line">script.<span class="property">src</span> = url;</span><br><span class="line"><span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">appendChild</span>(script);</span><br></pre></td></tr></table></figure>
|
|
146
|
+
|
|
147
|
+
<p>特别注意,服务器端需要设置:Access-Control-Allow-Origin</p>
|
|
148
|
+
<p>此外,我们也可以试试这个-<a target="_blank" rel="noopener" href="https://juejin.im/post/5c00a405f265da610e7fd024">解决 Script Error 的另类思路</a>:</p>
|
|
149
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> originAddEventListener = <span class="title class_">EventTarget</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">addEventListener</span>;</span><br><span class="line"><span class="title class_">EventTarget</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">addEventListener</span> = <span class="keyword">function</span> (<span class="params">type, listener, options</span>) {</span><br><span class="line"> <span class="keyword">const</span> wrappedListener = <span class="keyword">function</span> (<span class="params">...args</span>) {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">return</span> listener.<span class="title function_">apply</span>(<span class="variable language_">this</span>, args);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (err) {</span><br><span class="line"> <span class="keyword">throw</span> err;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> originAddEventListener.<span class="title function_">call</span>(<span class="variable language_">this</span>, type, wrappedListener, options);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
|
150
|
+
|
|
151
|
+
<p>简单解释一下:</p>
|
|
152
|
+
<ul>
|
|
153
|
+
<li>改写了 <code>EventTarget</code> 的 <code>addEventListener</code> 方法;</li>
|
|
154
|
+
<li>对传入的 <code>listener</code> 进行包装,返回包装过的 <code>listener</code>,对其执行进行 <code>try-catch</code>;</li>
|
|
155
|
+
<li>浏览器不会对 <code>try-catch</code> 起来的异常进行跨域拦截,所以 <code>catch</code> 到的时候,是有堆栈信息的;</li>
|
|
156
|
+
<li>重新 <code>throw</code> 出来异常的时候,执行的是同域代码,所以 <code>window.onerror</code> 捕获的时候不会丢失堆栈信息;</li>
|
|
157
|
+
</ul>
|
|
158
|
+
<p>利用包装 <code>addEventListener</code>,我们还可以达到「扩展堆栈」的效果:</p>
|
|
159
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"> (<span class="function">() =></span> {</span><br><span class="line"> <span class="keyword">const</span> originAddEventListener = <span class="title class_">EventTarget</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">addEventListener</span>;</span><br><span class="line"> <span class="title class_">EventTarget</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">addEventListener</span> = <span class="keyword">function</span> (<span class="params">type, listener, options</span>) {</span><br><span class="line">+ <span class="comment">// 捕获添加事件时的堆栈</span></span><br><span class="line">+ <span class="keyword">const</span> addStack = <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">`Event (<span class="subst">${type}</span>)`</span>).<span class="property">stack</span>;</span><br><span class="line"> <span class="keyword">const</span> wrappedListener = <span class="keyword">function</span> (<span class="params">...args</span>) {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">return</span> listener.<span class="title function_">apply</span>(<span class="variable language_">this</span>, args);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (err) {</span><br><span class="line">+ <span class="comment">// 异常发生时,扩展堆栈</span></span><br><span class="line">+ err.<span class="property">stack</span> += <span class="string">'\n'</span> + addStack;</span><br><span class="line"> <span class="keyword">throw</span> err;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> originAddEventListener.<span class="title function_">call</span>(<span class="variable language_">this</span>, type, wrappedListener, options);</span><br><span class="line"> }</span><br><span class="line"> })();</span><br></pre></td></tr></table></figure>
|
|
160
|
+
|
|
161
|
+
<h4 id="十一、崩溃和卡顿"><a href="#十一、崩溃和卡顿" class="headerlink" title="十一、崩溃和卡顿"></a>十一、崩溃和卡顿</h4><p>卡顿也就是网页暂时响应比较慢, <code>JS</code> 可能无法及时执行。但崩溃就不一样了,网页都崩溃了,<code>JS</code> 都不运行了,还有什么办法可以监控网页的崩溃,并将网页崩溃上报呢?</p>
|
|
162
|
+
<p>崩溃和卡顿也是不可忽视的,也许会导致你的用户流失。</p>
|
|
163
|
+
<p>1.利用 <code>window</code> 对象的 <code>load</code> 和 <code>beforeunload</code> 事件实现了网页崩溃的监控。<br>不错的文章,推荐阅读:<a target="_blank" rel="noopener" href="http://jasonjl.me/blog/2015/06/21/taking-action-on-browser-crashes/">Logging Information on Browser Crashes</a>。</p>
|
|
164
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">'load'</span>, <span class="keyword">function</span> (<span class="params"></span>) {</span><br><span class="line"> sessionStorage.<span class="title function_">setItem</span>(<span class="string">'good_exit'</span>, <span class="string">'pending'</span>);</span><br><span class="line"> <span class="built_in">setInterval</span>(<span class="keyword">function</span> (<span class="params"></span>) {</span><br><span class="line"> sessionStorage.<span class="title function_">setItem</span>(<span class="string">'time_before_crash'</span>, <span class="title function_">newDate</span>().<span class="title function_">toString</span>());</span><br><span class="line"> }, <span class="number">1000</span>);</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">'beforeunload'</span>, <span class="keyword">function</span> (<span class="params"></span>) {</span><br><span class="line"> sessionStorage.<span class="title function_">setItem</span>(<span class="string">'good_exit'</span>, <span class="string">'true'</span>);</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(sessionStorage.<span class="title function_">getItem</span>(<span class="string">'good_exit'</span>) &&</span><br><span class="line"> sessionStorage.<span class="title function_">getItem</span>(<span class="string">'good_exit'</span>) !== <span class="string">'true'</span>) {</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> insert crash logging code here</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"> <span class="title function_">alert</span>(<span class="string">'Hey, welcome back from your crash, looks like you crashed on: '</span> + sessionStorage.<span class="title function_">getItem</span>(<span class="string">'time_before_crash'</span>));</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
|
165
|
+
|
|
166
|
+
<p>2.基于以下原因,我们可以使用 <code>Service Worker</code> 来实现<a target="_blank" rel="noopener" href="https://juejin.im/entry/5be158116fb9a049c6434f4a?utm_source=gold_browser_extension">网页崩溃的监控</a>:</p>
|
|
167
|
+
<ul>
|
|
168
|
+
<li><code>Service Worker</code> 有自己独立的工作线程,与网页区分开,网页崩溃了,<code>Service Worker</code> 一般情况下不会崩溃;</li>
|
|
169
|
+
<li><code>Service Worker</code> 生命周期一般要比网页还要长,可以用来监控网页的状态;</li>
|
|
170
|
+
<li>网页可以通过 <code>navigator.serviceWorker.controller.postMessage API</code> 向掌管自己的 <code>SW</code> 发送消息。</li>
|
|
171
|
+
</ul>
|
|
172
|
+
<h4 id="十二、错误上报"><a href="#十二、错误上报" class="headerlink" title="十二、错误上报"></a>十二、错误上报</h4><p>1.通过 <code>Ajax</code> 发送数据<br>因为 <code>Ajax</code> 请求本身也有可能会发生异常,而且有可能会引发跨域问题,一般情况下更推荐使用动态创建 <code>img</code> 标签的形式进行上报。</p>
|
|
173
|
+
<p>2.动态创建 <code>img</code> 标签的形式</p>
|
|
174
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">functionreport</span>(error) {</span><br><span class="line"> <span class="keyword">let</span> reportUrl = <span class="string">'http://jartto.wang/report'</span>;</span><br><span class="line"> <span class="keyword">new</span> <span class="title class_">Image</span>().<span class="property">src</span> = <span class="string">`<span class="subst">${reportUrl}</span>?logs=<span class="subst">${error}</span>`</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
|
175
|
+
|
|
176
|
+
<p>收集异常信息量太多,怎么办?实际中,我们不得不考虑这样一种情况:如果你的网站访问量很大,那么一个必然的错误发送的信息就有很多条,这时候,我们需要设置采集率,从而<a target="_blank" rel="noopener" href="https://github.com/happylindz/blog/issues/5">减缓服务器的压力</a>:</p>
|
|
177
|
+
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Reporter</span>.<span class="property">send</span> = <span class="keyword">function</span>(<span class="params">data</span>) {</span><br><span class="line"> <span class="comment">// 只采集 30%</span></span><br><span class="line"> <span class="keyword">if</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() < <span class="number">0.3</span>) {</span><br><span class="line"> <span class="title function_">send</span>(data) <span class="comment">// 上报错误信息</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
|
178
|
+
|
|
179
|
+
<p>采集率应该通过实际情况来设定,随机数,或者某些用户特征都是不错的选择。</p>
|
|
180
|
+
<h4 id="十三、总结"><a href="#十三、总结" class="headerlink" title="十三、总结"></a>十三、总结</h4><p>回到我们开头提出的那个问题,如何优雅的处理异常呢?</p>
|
|
181
|
+
<p>1.可疑区域增加 <code>Try-Catch</code><br>2.全局监控 <code>JS</code> 异常 <code>window.onerror</code><br>3.全局监控静态资源异常 <code>window.addEventListener</code><br>4.捕获没有 <code>Catch</code> 的 <code>Promise</code> 异常:<code>unhandledrejection</code><br>5.<code>VUE errorHandler</code> 和 <code>React componentDidCatch</code><br>6.监控网页崩溃:<code>window</code> 对象的 <code>load</code> 和 <code>beforeunload</code><br>7.跨域 <code>crossOrigin</code> 解决</p>
|
|
182
|
+
<p>其实很简单,正如<a target="_blank" rel="noopener" href="http://jartto.wang/2018/11/20/js-exception-handling/">上文</a>所说:采用组合方案,分类型的去捕获异常,这样基本 80%-90% 的问题都化于无形。</p>
|
|
183
|
+
<h4 id="十四、参考"><a href="#十四、参考" class="headerlink" title="十四、参考"></a>十四、参考</h4><p><a target="_blank" rel="noopener" href="http://jasonjl.me/blog/2015/06/21/taking-action-on-browser-crashes/">Logging Information on Browser Crashes</a><br><a target="_blank" rel="noopener" href="https://github.com/happylindz/blog/issues/5">前端代码异常监控实战</a><br><a target="_blank" rel="noopener" href="https://blog.csdn.net/a986597353/article/details/78469979">Error Boundaries</a><br><a target="_blank" rel="noopener" href="https://github.com/RicardoCao-Biker/Front-End-Monitoring/blob/master/BasicKnowledge.md">前端监控知识点</a><br><a target="_blank" rel="noopener" href="https://blog.sentry.io/2016/01/04/client-javascript-reporting-window-onerror">Capture and report JavaScript errors with window.onerror</a></p>
|
|
184
|
+
</div><iframe src="/donate/?AliPayQR=https://store.xuehuayu.cn/store/public/alipay_qr.jpg&WeChatQR=https://store.xuehuayu.cn/store/public/wechat_qr.png&UnionPayQR=null&GitHub=null&BTCQR=null&BTCKEY=null&PayPal=https://www.paypal.com/paypalme/OrdinaryPerson" style="overflow-x:hidden; overflow-y:hidden; border:0xp none #fff; min-height:240px; width:100%;" frameborder="0" scrolling="no"></iframe><div><ul class="post-copyright"><li class="post-copyright-author"><strong>本文作者:</strong>雪花雨</li><li class="post-copyright-link"><strong>本文链接:</strong><a href="/article/18039.html">https://xuehuayu.cn/article/18039.html</a></li><li class="post-copyright-license"><strong>版权声明:</strong>① 标为原创的文章为博主原创,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接。② 转载文章来自网络,已标明出处,<a href="mailto:cainiaoblog@126.com">侵删</a>。</li></ul></div><br><div class="tags"><a href="/tags/%E8%BD%AC%E8%BD%BD/">转载</a></div><div class="post-nav"><a class="pre" href="/article/43724.html">种草 ES2020 新特性</a><a class="next" href="/article/41777.html">HTTPS 原理分析带着疑问层层深入</a></div><div id="vcomment"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@waline/client@v2/dist/waline.min.css"><script src="//cdn.jsdelivr.net/npm/@waline/client@v2/dist/waline.js"></script><script>const origin = window.location.origin
|
|
185
|
+
const serverURL = origin.includes('cainiaoblog') ? 'https://cmts.cainiaoblog.cn' : 'https://cmts.xuehuayu.cn'
|
|
186
|
+
const locale = {
|
|
187
|
+
placeholder: '请正确填写昵称和邮箱,方便接收回复通知~',
|
|
188
|
+
sofa: '沙发空缺中,还不快抢~',
|
|
189
|
+
};
|
|
190
|
+
Waline.init({
|
|
191
|
+
el: '#vcomment',
|
|
192
|
+
serverURL: serverURL,
|
|
193
|
+
pageSize: '20',
|
|
194
|
+
visitor: true, // 阅读量统计
|
|
195
|
+
requiredMeta: ['nick', 'mail'],
|
|
196
|
+
emoji: [
|
|
197
|
+
'https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/weibo',
|
|
198
|
+
'https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/qq',
|
|
199
|
+
'https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/tw-emoji',
|
|
200
|
+
],
|
|
201
|
+
locale,
|
|
202
|
+
pageview: true
|
|
203
|
+
})
|
|
204
|
+
</script></div></div></div><div class="pure-u-1 pure-u-md-1-4 fixed-search hidden_mid_and_down"><div id="sidebar"><script type="text/javascript" src="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/js/search.min.js"></script><div class="widget"><div class="widget-search"><input class="search" type="radio" name="search" value="baidu" id="baidu" checked="checked"/><label class="label" for="baidu" title="百度全站搜索">百度</label><input class="search" type="radio" name="search" value="google" id="google"/><label class="label" for="google" title="谷歌全站搜索">谷歌</label><input class="search" type="radio" name="search" value="self" id="self"/><label class="label" for="self" title="使用站内搜索">站内</label></div><div class="widget" id="search"><form class="search-form" action="//www.baidu.com/baidu" method="get" accept-charset="utf-8" target="_blank"><input type="search" name="word" maxlength="30" placeholder="百度全站搜索"/><input type="hidden" name="si" value="xuehuayu.cn"/><input type="hidden" name="cl" value="3"/><input type="hidden" name="ct" value="2097152"/><input type="hidden" name="s" value="on"/><input class="search-submit" type="submit" value=""/></form></div></div><script>$('input[type=radio][name=search]').change(function() {
|
|
205
|
+
var val = $(this).val()
|
|
206
|
+
var self = '<div class="search-form"><input id="local-search-input" placeholder="站内搜索,首次慢" type="search" name="q" results="0"><input class="search-submit" type="submit" value=""/><div id="local-search-result"></div></div>'
|
|
207
|
+
var google = '<form class="search-form" action="//www.google.com/search" method="get" accept-charset="utf-8" target="_blank"><input type="search" name="q" maxlength="30" placeholder="谷歌全站搜索"><input type="hidden" name="sitesearch" value="xuehuayu.cn"><input class="search-submit" type="submit" value=""/></form>'
|
|
208
|
+
var baidu = '<form class="search-form" action="//www.baidu.com/baidu" method="get" accept-charset="utf-8" target="_blank"><input type="search" name="word" maxlength="30" placeholder="百度全站搜索"><input type="hidden" name="si" value="xuehuayu.cn"><input type="hidden" name="cl" value="3"><input type="hidden" name="ct" value="2097152"><input type="hidden" name="s" value="on"><input class="search-submit" type="submit" value=""/></form>'
|
|
209
|
+
|
|
210
|
+
if (val === 'self') {
|
|
211
|
+
$('#search').html(self)
|
|
212
|
+
var search_path = 'search.xml';
|
|
213
|
+
if (search_path.length == 0) {
|
|
214
|
+
search_path = 'search.xml';
|
|
215
|
+
}
|
|
216
|
+
var path = 'https://cdn.staticaly.com/gh/npljy/npljy.github.io/main/' + search_path;
|
|
217
|
+
searchFunc(path, 'local-search-input', 'local-search-result');
|
|
218
|
+
} else if (val === 'baidu') {
|
|
219
|
+
$('#search').html(baidu)
|
|
220
|
+
} else if (val === 'google') {
|
|
221
|
+
$('#search').html(google)
|
|
222
|
+
}
|
|
223
|
+
})</script><div class="widget widget-wxmp"><img alt="微信公众号" width="100%" src="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/img/mp-mini.jpg"/></div><div class="widget widget-categories"><div class="widget-title"><i class="fa fa-folder-o"> 分类</i></div><ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/CDN/">CDN</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/IDE/">IDE</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/git/">git</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/hexo/">hexo</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%85%AC%E5%85%B1%E8%8A%82%E6%97%A5/">公共节日</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%88%86%E4%BA%AB/">分享</a><span class="category-list-count">29</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%89%8D%E7%AB%AF/">前端</a><span class="category-list-count">191</span><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%89%8D%E7%AB%AF/%E6%B5%8F%E8%A7%88%E5%99%A8/">浏览器</a><span class="category-list-count">1</span><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%89%8D%E7%AB%AF/%E6%B5%8F%E8%A7%88%E5%99%A8/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE/">网络协议</a><span class="category-list-count">1</span></li></ul></li></ul></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%8D%9A%E5%AE%A2/">博客</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%B7%A5%E5%85%B7/">工具</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%B9%BF%E5%91%8A%E8%BF%87%E6%BB%A4/">广告过滤</a><span class="category-list-count">8</span><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%B9%BF%E5%91%8A%E8%BF%87%E6%BB%A4/%E8%A7%86%E9%A2%91%E7%94%B5%E8%A7%86%E5%B0%8F%E8%AF%B4%E6%BC%AB%E7%94%BB%E8%B5%84%E8%AE%AF%E9%9F%B3%E4%B9%90/">视频电视小说漫画资讯音乐</a><span class="category-list-count">2</span></li></ul></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E6%AD%A3%E5%88%99/">正则</a><span class="category-list-count">5</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E6%B5%8F%E8%A7%88%E5%99%A8/">浏览器</a><span class="category-list-count">5</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E7%AE%97%E6%B3%95/">算法</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E8%B5%84%E8%AE%AF/">资讯</a><span class="category-list-count">16</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E8%BD%BB%E6%9D%BE%E4%B8%80%E5%88%BB/">轻松一刻</a><span class="category-list-count">1</span></li></ul></div><div class="widget widget-tags"><div class="widget-title"><i class="fa fa-star-o"> 标签</i></div><div class="tagcloud"><a href="/tags/%E5%8E%9F%E5%88%9B/" style="font-size: 15px;">原创</a> <a href="/tags/%E8%BD%AC%E8%BD%BD/" style="font-size: 15px;">转载</a> <a href="/tags/%E6%89%8B%E5%86%99/" style="font-size: 15px;">手写</a> <a href="/tags/%E7%96%AB%E6%83%85/" style="font-size: 15px;">疫情</a> <a href="/tags/%E5%A8%B1%E4%B9%90/" style="font-size: 15px;">娱乐</a></div></div><div class="widget widget-recent-posts"><div class="widget-title"><i class="fa fa-file-o"> 最近文章</i></div><ul class="post-list"><li class="post-list-item"><a class="post-list-link" href="/article/c5576490.html">面试准备</a></li><li class="post-list-item"><a class="post-list-link" href="/article/84c9ccd6.html">精读《SolidJS》</a></li><li class="post-list-item"><a class="post-list-link" href="/article/53803e6.html">git提交注释规范</a></li><li class="post-list-item"><a class="post-list-link" href="/article/a4145266.html">前端数组拍平flat一行代码</a></li><li class="post-list-item"><a class="post-list-link" href="/article/bedea419.html">一道前端this面试题</a></li><li class="post-list-item"><a class="post-list-link" href="/article/bf7e7421.html">git多账号配置</a></li></ul></div><div class="widget widget-links"><div class="widget-title"><i class="fa fa-external-link"> 友情链接</i></div><ul></ul><a href="https://github.com/npljy?utm_source=xuehuayu.cn" title="GitHub" target="_blank">GitHub</a><ul></ul><a href="https://laonongmin.online?utm_source=xuehuayu.cn" title="看看" target="_blank">看看</a><ul></ul><a href="https://cainiaoblog.cn?utm_source=xuehuayu.cn" title="菜鸟博客" target="_blank">菜鸟博客</a><ul></ul><a href="mailto:cainiaoblog@126.com" title="友链联系" target="_blank">友链联系</a></div></div></div><div class="pure-u-1 pure-u-md-3-4"><div id="footer"><div class="flex-block justify-center align-center flex-wrap"><a class="gxba-link" id="gxba" rel="nofollow" target="_blank" href="http://beian.miit.gov.cn/">京ICP备20007647号-2</a><a class="gaba-link" id="gaba-link" rel="nofollow" target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11010802031264"><img class="nofancybox" src="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/img/gaba.png" alt=""/><span id="gaba">京公网安备 11010802031264号</span><span style="padding-right: 10px;"></span></a><span>Copyright © 2023 </span><a href="/." rel="nofollow">前端壹菜鸟. </a><script>(function(){
|
|
224
|
+
var cnb =window.location.origin.indexOf('cainiaoblog') !==-1
|
|
225
|
+
if (cnb) {
|
|
226
|
+
var gxba =document.getElementById('gxba')
|
|
227
|
+
var gaba =document.getElementById('gaba')
|
|
228
|
+
var gabaLink =document.getElementById('gaba-link')
|
|
229
|
+
gxba.innerText ='京ICP备20007647号-1'
|
|
230
|
+
gaba.innerText ='京公网安备 11010802031254号'
|
|
231
|
+
gabaLink.setAttribute('href','http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11010802031254')
|
|
232
|
+
}
|
|
233
|
+
})()</script></div><div class="flex-block justify-center align-center flex-wrap"><a rel="nofollow" target="_blank" href="https://v6.51.la/s/Guz3lwHCsVme9Cu"><div class="busuanzi_container" id="busuanzi_container"><span class="busuanzi_container_site_pv" id="busuanzi_container_site_pv">访问量:<span id="busuanzi_value_site_pv"><i class="fa fa-spinner"></i></span></span><span class="busuanzi_container_site_uv" id="busuanzi_container_site_uv">访客数:<span id="busuanzi_value_site_uv"><i class="fa fa-spinner"></i></span></span><span style="padding-right: 10px;"></span></div></a><a rel="nofollow" target="_blank" href="https://www.upyun.com/?utm_source=lianmeng&utm_medium=referral"><span style="font-weight:bold;letter-spacing: 1px;">本网站由 </span><img class="nofancybox" height="32" style="vertical-align: middle" src="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/img/upy_logo.min.svg" alt=""/><span style="font-weight:bold;letter-spacing: 1px;">提供CDN加速/云存储服务</span></a><span style="padding-right: 10px;"></span><a rel="nofollow" style="font-size:18px;font-weight:bold;vertical-align: middle" target="_blank" title="注册就送代金券可直接使用" href="https://console.upyun.com/register/?invite=HyDsjZHIL">注册</a></div></div></div></div><a class="show" id="rocket" href="#top"></a><div class="darkmode-toggle">🌓</div><script type="text/javascript" src="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/js/totop.min.js" async></script><script type="text/javascript" src="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/js/dark.min.js" async></script><script type="text/javascript" src="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/js/codeblock-resizer.min.js"></script><script type="text/javascript" src="//cdn.staticaly.com/gh/npljy/npljy.github.io/main/js/smartresize.min.js"></script></div></body></html>
|