摘要:錯誤上報機制發送數據因為請求本身也有可能會發生異常,而且有可能會引發跨域問題,一般情況下更推薦使用動態創建標簽的形式進行上報。
js錯誤捕獲
js錯誤的實質,也是發出一個事件,處理他
error實例對象
對象屬性
message:錯誤提示信息
name:錯誤名稱(非標準屬性)宿主環境賦予
stack:錯誤的堆棧(非標準屬性)宿主環境賦予
對象類型(7種)
SyntaxError對象是解析代碼時發生的語法錯誤
ReferenceError對象是引用一個不存在的變量時發生的錯誤
RangeError對象是一個值超出有效范圍時發生的錯誤(一是數組長度為負數,二是Number對象的方法參數超出范圍,以及函數堆棧超過最大值)
TypeError對象是變量或參數不是預期類型時發生的錯誤:對字符串、布爾值、數值等原始類型的值使用new命令
URIError對象是 URI 相關函數的參數不正確時拋出的錯誤:使用函數不當
eval函數沒有被正確執行時,會拋出EvalError錯誤 - 不再使用,為了代碼兼容
自定義錯誤
function UserError(message) { this.message = message || "默認信息"; this.name = "UserError"; } UserError.prototype = new Error(); UserError.prototype.constructor = UserError; new UserError("這是自定義的錯誤!");Js運行時錯誤處理機制
try..catch…finally
范圍:用來捕獲任何類型的同步錯誤,可以捕獲async / await的代碼,但無法捕獲promise、setTimeout、dom回調(eg:onclick點擊回調)的代碼,在回調函數里面寫try…catch可以捕獲,但包在外面不會捕獲,無法捕獲語法錯誤
異步不捕獲原因:
async/await捕獲原因:
window.onerror
范圍:同步錯誤和異步錯誤都可以捕獲,但無法捕獲到靜態資源異常,或者接口異常(網絡請求異常不會事件冒泡,因此必須在捕獲階段將其捕捉到才行),無法捕獲語法錯誤
原理:當 JS 運行時錯誤發生時,window 會觸發一個 ErrorEvent 接口的 error 事件
參數
/** * @param {String} message 錯誤信息 * @param {String} source 出錯文件 * @param {Number} lineno 行號 * @param {Number} colno 列號
*/ window.onerror = function(message, source, lineno, colno, error) { console.log("捕獲到異常:",{message, source, lineno, colno, error}); } ```
補充:window.onerror 函數只有在返回 true 的時候,異常才不會向上拋出,否則即使是知道異常的發生控制臺還是會顯示 Uncaught Error: xxxxx
onerror 最好寫在所有 JS 腳本的前面,否則有可能捕獲不到錯誤;(捕獲的是全局錯誤)
資源加載錯誤window.addEventListener(一項資源(如圖片或腳本)加載失敗,加載資源的元素會觸發一個 Event 接口的 error 事件,并執行該元素上的onerror() 處理函數,有瀏覽器兼容問題)
注意:只能捕獲無法冒泡
window.addEventListener("error", (error) => { console.log("捕獲到異常:", error); }, true) // 一定要加true,捕獲但不冒泡
Script error跨域的靜態資源加載異常捕獲(cdn文件等)
跨域文件只會報Script error,沒有詳細信息,怎么解決:
客戶端:script標簽添加crossOrigin
服務端:設置:Access-Control-Allow-Origin
iframe異常
使用window.onerror
promise異常捕獲
沒有寫 catch 的 Promise 中拋出的錯誤無法被 onerror 或 try-catch 捕獲到
為了防止有漏掉的 Promise 異常,建議在全局增加一個對 unhandledrejection 的監聽,用來全局監聽Uncaught Promise Error
window.addEventListener("unhandledrejection", function(e){ console.log(e); });
補充:如果去掉控制臺的異常顯示,需要加上:event.preventDefault();
vue異常捕獲
VUE errorHandler
Vue.config.errorHandler = (err, vm, info) => { console.error("通過vue errorHandler捕獲的錯誤"); console.error(err); console.error(vm); console.error(info); }React異常捕獲
componentDidCatch(React16)
新概念Error boundary(React16):UI的某部分引起的 JS 錯誤不會破壞整個程序(只有 class component可以成為一個 error boundaries)
不會捕獲以下錯誤
1.事件處理器 2.異步代碼 3.服務端的渲染代碼 4.在 error boundaries 區域內的錯誤
Eg: 全局一個error boundary 組件就夠用啦
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, info) { // Display fallback UI this.setState({ hasError: true }); // You can also log the error to an error reporting service logErrorToMyService(error, info); } render() { if (this.state.hasError) { // You can render any custom fallback UI return頁面崩潰和卡頓處理Something went wrong.
; } return this.props.children; } }
卡頓
網頁暫時響應比較慢, JS 可能無法及時執行
解決:window 對象的 load 和 beforeunload 事件實現了網頁崩潰的監控
window.addEventListener("load", function () { sessionStorage.setItem("good_exit", "pending"); setInterval(function () { sessionStorage.setItem("time_before_crash", new Date().toString()); }, 1000); }); window.addEventListener("beforeunload", function () { sessionStorage.setItem("good_exit", "true"); }); if(sessionStorage.getItem("good_exit") && sessionStorage.getItem("good_exit") !== "true") { /* insert crash logging code here */ alert("Hey, welcome back from your crash, looks like you crashed on: " + sessionStorage.getItem("time_before_crash")); }
崩潰
JS 都不運行了,還有什么辦法可以監控網頁的崩潰,并將網頁崩潰上報呢
解決:Service Worker 來實現網頁崩潰的監控
Service Worker 有自己獨立的工作線程,與網頁區分開,網頁崩潰了,Service Worker一般情況下不會崩潰;
Service Worker 生命周期一般要比網頁還要長,可以用來監控網頁的狀態;
網頁可以通過 navigator.serviceWorker.controller.postMessage API 向掌管自己的 SW發送消息。
錯誤上報機制
Ajax 發送數據
因為 Ajax 請求本身也有可能會發生異常,而且有可能會引發跨域問題,一般情況下更推薦使用動態創建 img 標簽的形式進行上報。
動態創建 img 標簽的形式 更常用,簡單,無跨越問題
function report(error) { let reportUrl = "http://jartto.wang/report"; new Image().src = `${reportUrl}?logs=${error}`; }
如果你的網站訪問量很大,那么一個必然的錯誤發送的信息就有很多條,這時候,我們需要設置采集率,從而減緩服務器的壓力:
Reporter.send = function(data) { // 只采集 30% if(Math.random() < 0.3) { send(data) // 上報錯誤信息 } }js源代碼壓縮如何定位:成熟方案提供sentry
sentry 是一個實時的錯誤日志追蹤和聚合平臺,包含了上面 sourcemap 方案,并支持更多功能,如:錯誤調用棧,log 信息,issue管理,多項目,多用戶,提供多種語言客戶端等,
這里不過多敘述,之后在搭建sentry服務時,會再補篇博文
補充:node服務端錯誤處理機制全棧開發,后端采用express庫,在這里補充一下,node服務的錯誤處理方案
錯誤分類
一般錯誤處理:如某種回退,基本上只是說:“有錯誤,請再試一次或聯系我們”。這并不是特別聰明,但至少通知用戶,有地方錯了——而不是無限加載或進行類似地處理
特殊錯誤處理為用戶提供詳細信息,讓用戶了解有什么問題以及如何解決它,例如,有信息丟失,數據庫中的條目已經存在等等
步驟
1. 構建一個自定義 Error 構造函數:讓我們方便地獲得堆棧跟蹤
class CustomError extends Error { constructor(code = "GENERIC", status = 500, ...params) { super(...params) if (Error.captureStackTrace) { Error.captureStackTrace(this, CustomError) } this.code = code this.status = status } } module.exports = CustomError
2.處理路由:對于每一個路由,我們要有相同的錯誤處理行為
wT:在默認情況下,由于路由都是封裝的,所以 Express 并不真正支持那種方式
解決:實現一個路由處理程序,并把實際的路由邏輯定義為普通的函數。這樣,如果路由功能(或任何內部函數)拋出一個錯誤,它將返回到路由處理程序,然后可以傳給前端
const express = require("express") const router = express.Router() const CustomError = require("../CustomError") router.use(async (req, res) => { try { const route = require(`.${req.path}`)[req.method] try { const result = route(req) // We pass the request to the route function res.send(result) // We just send to the client what we get returned from the route function } catch (err) { /* This will be entered, if an error occurs inside the route function. */ if (err instanceof CustomError) { /* In case the error has already been handled, we just transform the error to our return object. */ return res.status(err.status).send({ error: err.code, description: err.message, }) } else { console.error(err) // For debugging reasons // It would be an unhandled error, here we can just return our generic error object. return res.status(500).send({ error: "GENERIC", description: "Something went wrong. Please try again or contact support.", }) } } } catch (err) { /* This will be entered, if the require fails, meaning there is either no file with the name of the request path or no exported function with the given request method. */ res.status(404).send({ error: "NOT_FOUND", description: "The resource you tried to access does not exist.", }) } }) module.exports = router // 實際路由文件 const CustomError = require("../CustomError") const GET = req => { // example for success return { name: "Rio de Janeiro" } } const POST = req => { // example for unhandled error throw new Error("Some unexpected error, may also be thrown by a library or the runtime.") } const DELETE = req => { // example for handled error throw new CustomError("CITY_NOT_FOUND", 404, "The city you are trying to delete could not be found.") } const PATCH = req => { // example for catching errors and using a CustomError try { // something bad happens here throw new Error("Some internal error") } catch (err) { console.error(err) // decide what you want to do here throw new CustomError( "CITY_NOT_EDITABLE", 400, "The city you are trying to edit is not editable." ) } } module.exports = { GET, POST, DELETE, PATCH, }
3.構建全局錯誤處理機制
process.on("uncaughtException", (error: any) => { logger.error("uncaughtException", error) }) process.on("unhandledRejection", (error: any) => { logger.error("unhandledRejection", error) })總結:
1.可疑區域增加 Try-Catch
2.全局監控 JS 異常 window.onerror
3.全局監控靜態資源異常 window.addEventListener
4.捕獲沒有 Catch 的 Promise 異常:unhandledrejection
5.VUE errorHandler 和 React componentDidCatch
6.監控網頁崩潰:window 對象的 load 和 beforeunload
7.跨域 crossOrigin 解決
http://jartto.wang/2018/11/20...
https://levelup.gitconnected....
https://zhuanlan.zhihu.com/p/... 更詳細 待補充
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/109644.html
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:關于,強烈推薦閱讀跨域資源共享詳解阮一峰另外,這里也整理了一個實現原理圖簡化版如何判斷是否是簡單請求瀏覽器將請求分成兩類簡單請求和非簡單請求。 前言 從剛接觸前端開發起,跨域這個詞就一直以很高的頻率在身邊重復出現,一直到現在,已經調試過N個跨域相關的問題了,16年時也整理過一篇相關文章,但是感覺還是差了點什么,于是現在重新梳理了一下。 個人見識有限,如有差錯,請多多見諒,歡迎提出iss...
閱讀 6964·2021-09-22 15:36
閱讀 5724·2021-09-02 10:20
閱讀 1884·2019-08-30 15:44
閱讀 2665·2019-08-29 14:06
閱讀 1163·2019-08-29 11:17
閱讀 1614·2019-08-26 14:05
閱讀 3111·2019-08-26 13:50
閱讀 1562·2019-08-26 10:26