我正在参加「掘金·启航计划」
页面崩溃 → 主线程卡死 → 应该单独开一个线程
Worker
浏览器兼容性检测
if (window.Worker){
...
}
Web Worker
web worker 的上下文中没有 window,也就是没有 document 等一系列 DOM 的方法
专用 worker
var myWorker = new Worker('worker.js')
myWorker.postMessage("hello")
myWorker.onmessage = (msg) => {}
// 终止 worker
myWorker.terinate()
worker 脚本中存在错误
当 worker 出现运行中错误时,它的 onerror 事件处理函数会被调用。它会收到一个扩展了 ErrorEvent接口的名为 error的事件。
注意:在我们的woker脚本中涉及网络上报,那么需要分成两种情况
-
如果业务希望由于监控本身的错误也被上报的话,那么我们可以在 onError 中自定义上报事件( 那么自定义上报事件的错误呢?隔着套娃? )
-
如果业务不希望的话,则需要关注内部调用 fetch / xhr.send 其实是被改写的,是否需要做一些特殊的处理
共享worker
一个共享 worker 可以被多个脚本使用——即使这些脚本正在被不同的 window、iframe 或者 worker 访问
只需要保证用到共享 worker 的页面是同源的就OK了
具体的内容可以去MDN上再详细了解一下,因为作为监控,使用 专用 worker 可能更加合适
需求分析
崩溃的来源
-
运行时的一些死循环
-
内存泄漏 → 爆栈了
-
特别长的任务
目标
-
需要判断是不是因为内存的问题导致的 → 上报的数据携带内存信息
-
long task 误判减少 → 时间阈值可以再变大一些,比如 10s
具体设计
- 服务端心跳检测,通过WebSocket/或者短轮询的方式,向服务端发送请求;一旦页面崩溃,就不会再发送了,服务端判断页面挂了,然后数据入库;
弊端也很明显,资源占用严重,不论是服务端资源,还是客户端资源
- 使用 Web Worker 单独开辟一个线程,进行心跳检测
-
Web Worker
- 定期 ( 6s ) 检查发送给客户端,客户端及时响应。
- 定期 ( 3s ) 检查当前客户端反应的状况
- 检测到崩溃后 → 行异常上报。
-
客戶端 接受到 Web Worker 的刺激后,返回一个心跳包
代码实现
主线程
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
const worker = new Worker("http://127.0.0.1:5173/src/work.js")
console.log(worker)
worker.onmessage =(e)=>{
console.log(e, "心跳检测啦")
worker.postMessage("正在活跃")
}
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
)
Worker.js
let status = "alive"
function post(){
console.log("卡死啦")
}
setInterval(()=>{
self.postMessage("hartBeat");
status = "dead";
setTimeout(()=>{
if(status == "dead"){
post();
}
}, 3000)
}, 6000)
self.onmessage = ()=>{
status = "alive"
console.log("接收到主线程啦")
}