<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          前端異常監(jiān)控和容災(zāi)

          共 7438字,需瀏覽 15分鐘

           ·

          2021-08-25 01:01

          點(diǎn)擊上方 程序員成長(zhǎng)指北,關(guān)注公眾號(hào)

          回復(fù)1,加入高級(jí)Node交流群

          異常就是程序出現(xiàn)了意料之外的情況,影響了程序最終的呈現(xiàn)結(jié)果。所以我們開(kāi)發(fā)的時(shí)候就非常有必要未雨綢繆,進(jìn)行異常監(jiān)控,以應(yīng)對(duì)突如其來(lái)的問(wèn)題.

          既可以增強(qiáng)用戶體驗(yàn),我們開(kāi)發(fā)者也能遠(yuǎn)程定位問(wèn)題,尤其是移動(dòng)端 盡管對(duì) JS 而言,異常一般只會(huì)使當(dāng)前執(zhí)行的任務(wù)中止,基本不會(huì)導(dǎo)致崩潰.

          可異常監(jiān)控卻是一個(gè)完善的前端方案必須具備的.

          接下來(lái)就針對(duì)我們前端,需要做的異常一一說(shuō)明

          異常監(jiān)控

          JS 執(zhí)行異常

          • 使用try-catch的話捕捉不到具體語(yǔ)法錯(cuò)誤和異步錯(cuò)誤,所以推薦用在可預(yù)見(jiàn)情況下的錯(cuò)誤監(jiān)控
          • 使用 window.onerror ,比try-catch強(qiáng),不過(guò)也捕獲不到資源加載異常或者接口異常,推薦用來(lái)捕獲預(yù)料之外的錯(cuò)誤

          兩者結(jié)合更好

          收集到的錯(cuò)誤信息打印出來(lái)是這樣子的

          window.onerror = function (msg, url, row, col, error{
              console.table({ msg, url, row, col, error: error.stack })
              let errorMsg = {
                  type'javascript',
                  // msg錯(cuò)誤消息,error是錯(cuò)誤對(duì)象,這里拿的是error.stack(異常信息)
                  msg: error && error.stack ? error.stack || msg, 
                  // 發(fā)生錯(cuò)誤的行數(shù)
                  row,
                  // 列數(shù),也就是第幾個(gè)字符
                  col,
                  // 發(fā)生錯(cuò)誤的頁(yè)面地址
                  url,
                  // 發(fā)生錯(cuò)誤的時(shí)間
                  timeDate.now()
              }
              
              // 然后可以把這個(gè) errorMsg 存到一個(gè)數(shù)組里,統(tǒng)一上報(bào)
              // 也可以直接上報(bào)
              Axios.post({ 'https://xxxx', errorMsg })
              
              // 如果return true,錯(cuò)誤就不會(huì)拋到控制臺(tái)
          }

          上報(bào)有兩種方式,一種是如上面代碼中的用 AJAX,會(huì)有跨域所以需要服務(wù)端支持;還有一種是用 Image 對(duì)象,這有一個(gè)好處就是圖片請(qǐng)求沒(méi)有跨域;注意URL長(zhǎng)度不要超過(guò)限制就行。后面的例子中就不一一列舉了

          let url = 'https://xxx' + '錯(cuò)誤信息'
          new Image.src = url

          資源加載異常

          使用 addEventListener('error', callback, true) 在捕獲階段捕捉資源加載錯(cuò)誤信息,然后上報(bào)服務(wù)器

          使用 addEventListener('error', callback, true) 在捕獲階段捕捉資源加載錯(cuò)誤信息,然后上報(bào)服務(wù)器

          Promise 異常

          unhandledrejection

          使用 addeventListener('unhandledrejection',callback)捕獲 Promise 錯(cuò)誤。不過(guò)捕捉不到行數(shù),觸發(fā)時(shí)間在被 reject 但沒(méi)有 reject 處理的時(shí)候,可能發(fā)生在 window 下,也可能在 Worker 中

          window.addEventListener("unhandledrejection", (e) => {
              console.log(e)
              let errorMsg = {
                  type'promise',
                  msg: e.reason.stack || e.reason
                  // .....
              }
              Axios.post({ 'https://xxxx', errorMsg })
              
              // 如果return true,錯(cuò)誤就不會(huì)拋到控制臺(tái)
          })
          new Promise(() => {
              s
          })

          打印出來(lái)是這么個(gè)東西

          rejectionhandled

          Promise 錯(cuò)誤已被處理會(huì)觸發(fā)這個(gè)

          window.addEventListener("unhandledrejection", (e) => {
              console.log('錯(cuò)誤了')
          })
          window.addEventListener("rejectionhandled", (e) => {
              console.log('錯(cuò)誤已經(jīng)處理了')
          })

          Vue 異常

          errorHandle

          Vue為組件呈現(xiàn)函數(shù)和監(jiān)視程序期間沒(méi)有捕獲的錯(cuò)誤分配的一個(gè)處理程序。不過(guò)這個(gè)方法一旦捕獲取錯(cuò)誤后,錯(cuò)誤就不會(huì)拋到控制臺(tái)

          Vue.config.errorHandler = (err, vm, info) => {
              // err 錯(cuò)誤處理
              // vm vue實(shí)例
              // info 是特定于vue的錯(cuò)誤信息,比如哪個(gè)生命周期勾子

              // 如果需要把錯(cuò)誤拋到控制臺(tái),需要在這里加上這一行
              console.error(err)
          }

          warnHandle

          是Vue警告分配一個(gè)自定義處理程序。不過(guò)只在開(kāi)發(fā)環(huán)境有效,生產(chǎn)環(huán)境會(huì)被自忽略

          Vue.config.warnHandle = (msg, vm, trace){
              // trace 是組件層次結(jié)構(gòu)
          }

          renderError

          默認(rèn)的渲染函數(shù)遇到錯(cuò)誤時(shí),提供了一個(gè)代替渲染輸出的。這個(gè)和熱重新加載一起用會(huì)很棒

          new Vue({
              render (h){
                  throw new Error('oops')
              },
              renderError (h, err){
                  return h('per',{ style: { color: red } }, err.stack)
              }
          }).$mount('#app')

          errorCaptured

          任何派生組件捕獲錯(cuò)誤時(shí)調(diào)用。它可以 return false 來(lái)阻止錯(cuò)誤傳播。可以在這個(gè)勾子里修改組件狀態(tài)。不過(guò)如果是在模板或呈現(xiàn)函數(shù)里有條件語(yǔ)句,在捕獲到錯(cuò)誤時(shí),這些條件語(yǔ)句會(huì)短路,可能進(jìn)入一個(gè)無(wú)限渲染循環(huán)

          Vue.component('ErrorBoundary',{
              data() => { ... }
              errorCaptured(err, vm, info){
                  // err 錯(cuò)誤信息  
                  // vm 觸發(fā)錯(cuò)誤的組件實(shí)例 
                  // info 錯(cuò)誤捕獲位置信息
                  return false
              }
          })

          React 異常

          getDerivedStateFromError

          React 也有自帶的捕獲所有子組件中錯(cuò)誤的方法,這個(gè)生命周期會(huì)在后代組件拋出錯(cuò)誤時(shí)被調(diào)用。注意這個(gè)是在渲染階段調(diào)用的,所以不允許出現(xiàn)副作用

          class ErrorBoundary extends React.Component {
              constructor(props) {
                  super(props)
                  this.state = { hasErrorfalse }
              } 
              static getDerivedStateFromError(error) {
                  // 更新 state 使下一次渲染可以顯降級(jí) UI
                  return { hasErrortrue }
              }
          }

          componentDidCatch

          這個(gè)生命周期也會(huì)在后代組件拋出錯(cuò)誤時(shí)被調(diào)用,但是不會(huì)捕獲事件處理器和異步代碼的異常。它會(huì)在【提交】階段被調(diào)用,所以允許出現(xiàn)副作用

          class ErrorBoundary extends React.Component {
              constructor(props) {
                  super(props)
              } 
              componentDidCatch(error, info){
                  // error 錯(cuò)誤信息
                  // info.componentStack 錯(cuò)誤組件位置
              }
          }

          說(shuō)了前端可能發(fā)生的各種異常處理,那么后端異常呢?前端容災(zāi)就是

          前端容災(zāi)

          前端容災(zāi)指的因?yàn)楦鞣N原因后端接口掛了(比如服務(wù)器斷電斷網(wǎng)等等),前端依然能保證頁(yè)面信息能完整展示。

          比如 banner 或者列表之類(lèi)的等等數(shù)據(jù)是從接口獲取的,要是接口獲取不到了,怎么辦呢?

          LocalStorage

          首先,使用 LocalStorage

          在接口正常返回的時(shí)候把數(shù)據(jù)都存到 LocalStorage ,可以把接口路徑作為 key,返回的數(shù)據(jù)作為 value。

          然后之次再請(qǐng)求,只要請(qǐng)求失敗,就讀取 LocalStorage,把上次的數(shù)據(jù)拿出來(lái)展示,并上報(bào)錯(cuò)誤信息,以獲得緩沖時(shí)間

          CDN

          同時(shí),每次更新都要備份一份靜態(tài)數(shù)據(jù)放到CDN

          在接口請(qǐng)求失敗的時(shí)候,并且 LocalStorage 也沒(méi)有數(shù)據(jù)的情況下,就去 CDN 摘取備份的靜態(tài)數(shù)據(jù)

          Service Worker

          假如不只是接口數(shù)據(jù),整個(gè) html 都想存起來(lái),就可以使用 Service Worker 做離線存儲(chǔ)

          利用 Service Worker 的請(qǐng)求攔截,不管是存接口數(shù)據(jù),還是存頁(yè)面靜態(tài)資源文件都可以

          // 攔截所有請(qǐng)求事件 緩存中有請(qǐng)求的數(shù)據(jù)就直接用緩存,否則去請(qǐng)求數(shù)據(jù) 
          self.addEventListener('fetch', e => { 
              // 查找request中被緩存命中的response 
              e.respondWith(caches.match(e.request).then( response => { 
                  if (response) { 
                      return response 
                  } 
                  console.log('fetch source'
              })) 
          })

          做好這些,整個(gè)網(wǎng)站就完全可以離線運(yùn)行了

          Node 社群


          我組建了一個(gè)氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對(duì)Node.js學(xué)習(xí)感興趣的話(后續(xù)有計(jì)劃也可以),我們可以一起進(jìn)行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。


             “分享、點(diǎn)贊在看” 支持一波 

          瀏覽 74
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色婷婷五月天网站 | 日日射AV | 精品无码第一页 | 在线内射视频 | 日日干免费视频 |