当前位置: 首页 > news >正文

记录--解决前端内存泄漏:问题概览与实用解决方案

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

内存泄漏是前端开发中的一个常见问题,可能导致项目变得缓慢、不稳定甚至崩溃。在本文中,我们将深入探讨在JavaScript、Vue和React项目中可能导致内存泄漏的情况,并提供详细的代码示例,以帮助开发人员更好地理解和解决这些问题。

第一部分:JavaScript中的内存泄漏

1. 未正确清理事件处理器

JavaScript中的事件处理器是内存泄漏的常见来源之一。当你向DOM元素添加事件处理器时,如果不适当地删除这些事件处理器,它们会持有对DOM的引用,妨碍垃圾回收器释放相关的内存。

// 错误的示例:未删除事件处理器
const button = document.querySelector('#myButton');button.addEventListener('click', function() {// 一些操作
});// 忘记删除事件处理器
// button.removeEventListener('click', ??);

解决方法:在不再需要事件处理器时,务必使用removeEventListener来移除它们。

2. 循环引用

循环引用是另一个可能导致内存泄漏的情况。当两个或多个对象相互引用时,即使你不再使用它们,它们也无法被垃圾回收。

// 错误的示例:循环引用
function createObjects() {const obj1 = {};const obj2 = {};obj1.ref = obj2;obj2.ref = obj1;return 'Objects created';
}createObjects();

解决方法:确保在不再需要对象时,将其引用设置为null,打破循环引用。

function createObjects() {const obj1 = {};const obj2 = {};obj1.ref = obj2;obj2.ref = obj1;// 手动打破循环引用obj1.ref = null;obj2.ref = null;return 'Objects created';
}

3. 未释放大型数据结构

在JavaScript项目中,特别是处理大型数据集合时,未释放这些数据结构可能导致内存泄漏。

// 错误的示例:未释放大型数据结构
let largeData = null;function loadLargeData() {largeData = [...Array(1000000).keys()]; // 创建一个包含100万项的数组
}loadLargeData();// 忘记将largeData设置为null

解决方法:当你不再需要大型数据结构时,将其设置为null以释放内存。

function loadLargeData() {largeData = [...Array(1000000).keys()];// 使用largeData后// 不再需要它largeData = null;
}

4. 未正确清理定时器和间隔器

使用setTimeoutsetInterval创建定时器和间隔器时,如果不及时清理它们,它们会持续运行,可能导致内存泄漏。

// 错误的示例:未清理定时器
let timer;function startTimer() {timer = setInterval(function() {// 一些操作}, 1000);
}startTimer();// 忘记清理定时器
// clearInterval(timer);

解决方法:在不再需要定时器或间隔器时,使用clearTimeoutclearInterval来清理它们。

5. 使用闭包保留对外部作用域的引用

在JavaScript中,闭包可以访问其父作用域的变量。如果不小心,闭包可能会保留对外部作用域的引用,导致外部作用域的变量无法被垃圾回收。

// 错误的示例:使用闭包保留外部作用域的引用
function createClosure() {const data = '敏感数据';return function() {console.log(data);};
}const closure = createClosure();// closure保留了对data的引用,即使不再需要data

解决方法:在不再需要闭包时,确保解除对外部作用域的引用。

function createClosure() {const data = '敏感数据';return function() {console.log(data);};
}let closure = createClosure();// 在不再需要闭包时,解除引用
closure = null;

这些是JavaScript中可能导致内存泄漏的常见情况。现在让我们深入了解Vue和React中的内存泄漏问题。

第二部分:Vue中的内存泄漏

1. 未取消事件监听

在Vue中,当你使用$on方法添加事件监听器时,如果在组件销毁前未取消监听,可能会导致内存泄漏。

<template><div><button @click="startListening">Start Listening</button></div>
</template><script>
export default {methods: {startListening() {this.$on('custom-event', this.handleCustomEvent);},handleCustomEvent() {// 处理自定义事件},beforeDestroy() {// 错误的示例:未取消事件监听// this.$off('custom-event', this.handleCustomEvent);}}
};
</script>

在上述示例中,我们添加了一个自定义事件监听器,但在组件销毁前未取消监听。

解决方法:确保在组件销毁前使用$off来取消事件监听。

<template><div><button @click="startListening">Start Listening</button></div>
</template><script>
export default{methods: {startListening() {this.$on('custom-event', this.handleCustomEvent);},handleCustomEvent() {// 处理自定义事件},beforeDestroy() {// 取消事件监听this.$off('custom-event', this.handleCustomEvent);}}
};
</script>

2. 未正确清理定时器

在Vue中,使用setIntervalsetTimeout创建定时器时,需要注意清理定时器,否则它们将在组件销毁后继续运行。

<template><div><button @click="startTimer">Start Timer</button></div>
</template><script>
export default {data() {return {message: 'Hello, Vue!'};},methods: {startTimer() {this.timer = setInterval(() => {// 一些操作}, 1000);},beforeDestroy() {// 错误的示例:未清理定时器// clearInterval(this.timer);}}
};
</script>

在上述示例中,我们创建了一个定时器,但在组件销毁前没有清理它。

解决方法:在beforeDestroy钩子中清理定时器。

<template><div><button @click="startTimer">Start Timer</button></div>
</template><script>
export default {data() {return {message: 'Hello, Vue!'};},methods: {startTimer() {this.timer = setInterval(() => {// 一些操作}, 1000);},beforeDestroy() {// 清理定时器clearInterval(this.timer);}}
};
</script>

3. 未销毁Vue的子组件

在Vue中,如果子组件未正确销毁,可能会导致内存泄漏。这经常发生在使用动态组件或路由时。

<template><div><button @click="toggleComponent">Toggle Component</button><keep-alive><my-component v-if="showComponent" /></keep-alive></div>
</template><script>
import MyComponent from './MyComponent.vue';export default {data() {return {showComponent: false};},components: {MyComponent},methods: {toggleComponent() {this.showComponent = !this.showComponent;}}
};
</script>

在上述示例中,我们使用<keep-alive>包裹了<my-component>,以保持其状态,但如果在组件销毁前未将其销毁,可能会导致内存泄漏。

解决方法:确保在不再需要组件时,调用$destroy方法,以手动销毁Vue子组件。

<template><div><button @click="toggleComponent">Toggle Component</button><keep-alive><my-component v-if="showComponent" ref="myComponent" /></keep-alive></div>
</template><script>
import MyComponent from './MyComponent.vue';export default {data() {return {showComponent: false};},components: {MyComponent},methods: {toggleComponent() {if (this.showComponent) {// 销毁组件this.$refs.myComponent.$destroy();}this.showComponent = !this.showComponent;}}
};
</script>

4. 未取消异步操作或请求

在Vue中,如果组件中存在未取消的异步操作或HTTP请求,这些操作可能会保留对组件的引用,即使组件已销毁,也会导致内存泄漏。

<template><div><p>{{ message }}</p></div>
</template><script>
export default {data() {return {message: 'Hello, Vue!'};},created() {this.fetchData(); // 发起HTTP请求},beforeDestroy() {// 错误的示例:未取消HTTP请求// this.cancelHttpRequest();},methods: {fetchData() {this.$http.get('/api/data').then(response => {this.message = response.data;});},cancelHttpRequest() {// 取消HTTP请求逻辑}}
};
</script>

在上述示例中,我们发起了一个HTTP请求,但在组件销毁前未取消它。

解决方法:确保在组件销毁前取消异步操作、清理未完成的请求或使用适当的取消机制。

<template><div><p>{{ message }}</p></div>
</template><script>
export default {data() {return {message: 'Hello, Vue!'};},created() {this.fetchData(); // 发起HTTP请求},beforeDestroy() {// 取消HTTP请求this.cancelHttpRequest();},methods: {fetchData() {this.$http.get('/api/data').then(response => {this.message = response.data;});},cancelHttpRequest() {// 取消HTTP请求逻辑// 注意:需要实现取消HTTP请求的逻辑}}
};
</script>

5. 长时间保持全局状态

在Vue应用中,如果全局状态(例如使用Vuex管理的状态)被长时间保持,即使不再需要,也可能导致内存泄漏。

// 错误的示例:长时间保持全局状态
const store = new Vuex.Store({state: {// 大型全局状态},mutations: {// 修改全局状态}
});// 在整个应用生命周期中保持了store的引用
解决方法:在不再需要全局状态时,可以销毁它,或者在适当的时候清理它以释放内存。
// 正确的示例:销毁全局状态
const store = new Vuex.Store({state: {// 大型全局状态},mutations: {// 修改全局状态}
});// 在不再需要全局状态时,销毁它
store.dispatch('logout'); // 示例:登出操作

这些是Vue中可能导致内存泄漏的一些情况。接下来,我们将讨论React中的内存泄漏问题。

第三部分:React中的内存泄漏

1. 使用第三方库或插件

在React项目中使用第三方库或插件时,如果这些库不正确地管理自己的资源或事件监听器,可能会导致内存泄漏。这些库可能会在组件被销毁时保留对组件的引用。

import React, { Component } from 'react';
import ThirdPartyLibrary from 'third-party-library';class MyComponent extends Component {componentDidMount() {this.thirdPartyInstance = new ThirdPartyLibrary();this.thirdPartyInstance.init();}componentWillUnmount() {// 错误的示例:未正确销毁第三方库的实例// this.thirdPartyInstance.destroy();}render() {return <div>My Component</div>;}
}

在上述示例中,我们在componentDidMount中创建了一个第三方库的实例,但在componentWillUnmount中未正确销毁它。

解决方法:当使用第三方库或插件时,请查看其文档,了解如何正确销毁和清理资源。确保在组件卸载时调用所需的销毁方法。

import React, { Component } from 'react';
import ThirdPartyLibrary from 'third-party-library';class MyComponent extends Component {componentDidMount() {this.thirdPartyInstance = new ThirdPartyLibrary();this.thirdPartyInstance.init();}componentWillUnmount() {// 正确的示例:销毁第三方库的实例this.thirdPartyInstance.destroy();}render() {return <div>My Component</div>;}
}

2. 使用React Portals(续)

在React中,如果使用React Portals来渲染内容到其他DOM树的部分,需要确保在组件销毁时正确卸载Portal,以免内存泄漏。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';class PortalComponent extends Component {constructor(props) {super(props);this.portalContainer = document.createElement('div');}componentDidMount() {// 错误的示例:未卸载Portaldocument.body.appendChild(this.portalContainer);ReactDOM.createPortal(<div>Portal Content</div>, this.portalContainer);}componentWillUnmount() {// 错误的示例:未卸载Portaldocument.body.removeChild(this.portalContainer);}render() {return null;}
}

在上述示例中,我们创建了一个Portal,并将其附加到了DOM中,但未在组件销毁时正确卸载它。

解决方法:确保在组件卸载前正确卸载Portal。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';class PortalComponent extends Component {constructor(props) {super(props);this.portalContainer = document.createElement('div');}componentDidMount() {document.body.appendChild(this.portalContainer);}componentWillUnmount() {// 正确的示例:卸载Portaldocument.body.removeChild(this.portalContainer);}render() {// 在组件卸载后,Portal被正确卸载return ReactDOM.createPortal(<div>Portal Content</div>, this.portalContainer);}
}

3. 长时间保持Context

在React中,如果使用React Context来管理全局状态,并且长时间保持了对Context的引用,可能会导致内存泄漏。

// 错误的示例:长时间保持Context引用
const MyContext = React.createContext();function MyApp() {const contextValue = useContext(MyContext);// 长时间保持对Context的引用// 导致相关组件无法被垃圾回收
}

解决方法:在不再需要Context时,确保取消对它的引用,以便相关组件可以被垃圾回收。

// 正确的示例:取消Context引用
const MyContext = React.createContext();function MyApp() {const contextValue = useContext(MyContext);// 在不再需要Context时,解除引用// contextValue = null;
}

这些是React中可能导致内存泄漏的一些情况。通过了解这些潜在问题以及如何解决它们,你可以更好地编写稳定和高性能的React项目。

4、长时间保持未卸载的组件

在React中,如果长时间保持未卸载的组件实例,可能会导致内存泄漏。这通常发生在路由导航或动态组件加载的情况下。

import React, { Component } from 'react';
import { Route } from 'react-router-dom';class App extends Component {render() {return (<div>{/* 错误的示例:长时间保持未卸载的组件 */}<Route path="/page1" component={Page1} /><Route path="/page2" component={Page2} /></div>);}
}

在上述示例中,如果用户在/page1/page2之间切换,组件Page1Page2的实例将一直存在,即使不再需要。

解决方法:确保在不再需要的情况下卸载组件。使用React Router等路由库时,React会自动卸载不再匹配的组件。

import React, { Component } from 'react';
import { Route } from 'react-router-dom';class App extends Component {render() {return (<div>{/* 正确的示例:React会自动卸载不匹配的组件 */}<Route path="/page1" component={Page1} /><Route path="/page2" component={Page2} /></div>);}
}

5. 遗留的事件监听器

在React中,使用类组件时,未正确清理事件监听器可能会导致内存泄漏。

import React, { Component } from 'react';class MyComponent extends Component {componentDidMount() {window.addEventListener('resize', this.handleResize);}componentWillUnmount() {// 错误的示例:未移除事件监听器// window.removeEventListener('resize', this.handleResize);}handleResize() {// 处理窗口大小调整事件}render() {return <div>My Component</div>;}
}

在上述示例中,我们添加了窗口大小调整事件的监听器,但在组件卸载前未正确移除它。

解决方法:确保在组件卸载时移除所有事件监听器。

import React, { Component } from 'react';class MyComponent extends Component {componentDidMount() {window.addEventListener('resize', this.handleResize);}componentWillUnmount() {// 正确的示例:移除事件监听器window.removeEventListener('resize', this.handleResize);}handleResize() {// 处理窗口大小调整事件}render() {return <div>My Component</div>;}
}

总结

内存泄漏是前端开发中一个常见但容易忽视的问题。在JavaScript、Vue和React项目中,不正确的内存管理可能导致性能下降、项目不稳定甚至崩溃。为了避免内存泄漏,我们应谨慎处理事件处理器、定时器、循环引用和引用非受控组件等问题,并确保在组件销毁前正确清理资源。使用开发者工具和性能分析工具来监测和诊断潜在的内存泄漏问题,以确保你的前端项目在长时间运行时表现出色。通过正确处理内存管理问题,你可以提高项目的性能、稳定性和用户体验。

本文转载于:

https://juejin.cn/post/7272013476222763060

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

相关文章:

记录--解决前端内存泄漏:问题概览与实用解决方案

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 内存泄漏是前端开发中的一个常见问题&#xff0c;可能导致项目变得缓慢、不稳定甚至崩溃。在本文中&#xff0c;我们将深入探讨在JavaScript、Vue和React项目中可能导致内存泄漏的情况&#xff0c;并提…...

IP初学习

1.IP报文 首部长度指的是报头长度&#xff0c;用于分离报头和有效载荷 2.网段划分 IP地址 目标网络 目标主机 3.例子 4.特殊的IP地址 5.真正的网络环境 6.调制解调器 “猫”&#xff0c;学名叫宽带无线猫 7.NAT 源IP在内网环境不断被替换 8.私有IP不能出现在公网上 因…...

live5555 testProgs目录

文章目录 测试testProgs视频流直播流注意&#xff1a; 测试 testProgs 当涉及到许多示例程序时&#xff0c;解释每一个都可能会变得非常冗长。然而&#xff0c;我可以为你提供一些关键示例程序的简要解释&#xff0c;以帮助你了解每个示例的用途和功能&#xff1a; testOnDem…...

yolov5模型s,l,m,x的区别

yolov5s 是什么&#xff1f;yolov5系列最小的模型&#xff0c;s是small。 适合什么情况下使用&#xff1f;适合在计算资源有限的设备上使用。如移动设备或边缘设备。 速度和准确率&#xff1a;速度最快&#xff0c;准确率最低。 输入分辨率&#xff1a;通常为640x640 # Param…...

Springboot 实践(13)spring boot 整合RabbitMq

前文讲解了RabbitMQ的下载和安装&#xff0c;此文讲解springboot整合RabbitMq实现消息的发送和消费。 1、创建web project项目&#xff0c;名称为“SpringbootAction-RabbitMQ” 2、修改pom.xml文件&#xff0c;添加amqp使用jar包 <!-- RabbitMQ --> <dependency&g…...

YoloV8改进策略:轻量级Slim Neck打造极致的YoloV8

文章目录 摘要Yolov8官方结果源码改进方法测试结果总结摘要 论文链接:https://arxiv.org/ftp/arxiv/papers/2206/2206.02424.pdf 作者研究了增强 CNN 学习能力的通用方法,例如 DensNet、VoVNet 和 CSPNet,然后根据这些方法的理论设计了 Slim-Neck 结构。 使用轻量级卷积…...

使用java代码给Excel加水印,代码全,进阶版

以下代码&#xff0c;亲测可以跑通 1、上一篇博客用了Apache POI库3.8的版本的形式对Excel加了水印&#xff0c;但是最近主线版本用了4.1.2的形式&#xff0c;由于为了保持版本的兼容性&#xff0c;下面有开发了Apache POI的4.1.2的版本号的方案。 pom文件为&#xff1a; <d…...

day37:网编day4,多点通信和并发服务器

一、广播接收方&#xff1a; #include <myhead.h>#define ERR_MSG(msg) do{\ fprintf(stderr,"__%d__\n",__LINE__);\ perror(msg);\ }while(0)#define BRD_IP "192.168.114.255" #define BRD_PORT 8888int main(int argc, const char *argv[]) {//…...

STM32 硬件IIC 控制OLED I2C卡死问题

1. STM32L151C8T6 硬件IIC 控制OLED 屏&#xff0c;OLED 驱动IC CH1116G, 查阅OLED 数据手册 2. STM32 硬件IIC 初始化&#xff0c;用的标准库&#xff0c;固件库 // stm32l151c8t6 as master, oled control ic (CH1116G) as slave, and communicate by master iic2 void STM3…...

Redis图文指南

1、什么是 Redis&#xff1f; Redis&#xff08;REmote DIctionary Service&#xff09;是一个开源的键值对数据库服务器。 Redis 更准确的描述是一个数据结构服务器。Redis 的这种特殊性质让它在开发人员中很受欢迎。 Redis不是通过迭代或者排序方式处理数据&#xff0c;而是…...

C++17 std::string_view介绍与使用

std::string_view介绍 std::string_view是C17增加的新内容。它是一个轻量级的、只读的字符串视图&#xff0c;可以用来表示一个字符串或字符串的一部分。std::string_view可以提高代码的可读性、可维护性和性能。 std::string_view与std::string的主要区别在于&#xff0c;st…...

写得了代码,焊得了板!嵌入式开发工程师必修之代码管理方案(下)

目录 极狐GitLab嵌入式开发场景解决方案 3.1 高可用部署与灾备 3.2 组织管理 3.3 分支策略 3.4 分支保护 3.5 推送规则 3.6 代码评审 3.7 数据保护 3.8 其他相关 本文来自 武让 极狐GitLab 高级解决方案架构师 &#x1f4a1; 前两篇文章&#xff0c;作者介绍了嵌入式开…...

Matlab论文插图绘制模板第110期—水平双向柱状图

在之前的文章中&#xff0c;分享了很多Matlab柱状图的绘制模板&#xff1a; 进一步&#xff0c;再来看一种特殊的柱状图&#xff1a;水平双向柱状图。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自行下…...

【广州华锐互动】VR全景工厂虚拟导览,虚拟现实技术提升企业数字化信息管理水平

随着工业4.0的到来&#xff0c;VR工厂全景制作成为了越来越多工业企业的选择。传统的工厂管理方式往往存在诸多问题&#xff0c;如信息不对称、安全隐患等。为了解决这些问题&#xff0c;VR工厂全景制作应运而生&#xff0c;它通过结合虚拟现实现实技术和数据采集技术&#xff…...

idea 创建mybatis xml文件时找不到

1、File >Settings 如图 &#xff1a; 2、添加模板&#xff1a;如下图 3、添加xml模板 如下图&#xff1a; 模板内容&#xff1a; <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//E…...

Python钢筋混凝土结构计算.pdf-混凝土构件计算

计算原理&#xff1a; 代码实现&#xff1a; #钢筋混凝土参数 def c_hrb(): global fcuk,HRB,Ec,fc,ft,ftk,Es,fy,fyp,fyk global a1,epsilon_cu fcukEcfcftftk0.0 HRBEsfyfypfyk0.0 #矩形应力图系数a1&#xff0c;C50以下为1.0 a11.0 #正截面混凝土极限压应变epsilon_cu&#…...

mysql5.7-基于docker-compose搭建主从同步

一、环境信息 系统版本&#xff1a;CentOS Linux release 7.9.2009 (Core) cat /etc/centos-release Docker版本&#xff1a;Docker version 20.10.6, build 370c289 docker --version Docker-compose版本&#xff1a;Docker Compose version v2.10.2 docker-compose --versio…...

【USRP】调制解调系列5:16QAM、32QAM、64QAM、256QAM、1024QAM、基于labview的实现

QAM 正交振幅键控是一种将两种调幅信号&#xff08;2ASK和2PSK&#xff09;汇合到一个信道的方法&#xff0c;因此会双倍扩展有效带宽&#xff0c;正交调幅被用于脉冲调幅。正交调幅信号有两个相同频率的载波&#xff0c;但是相位相差90度&#xff08;四分之一周期&#xff0c…...

Odoo|5分钟创建自定义的业务系统唯一序列号

在业务操作中&#xff0c;经常会遇到需要生成全局唯一序列号数据的情况&#xff0c;比如订单号、报价单号等。为了确保数据的唯一性和准确性&#xff0c;通常我们会使用Redis或其他分布式锁机制来实现。然而&#xff0c;很多人可能不知道&#xff0c;odoo框架本身提供了一个原生…...

mysql索引为什么提高查询速度(底层原理)

一、索引原理图 二、索引数据存储到硬盘而不是内存&#xff1f; 硬盘内存 成本低成本高 容量大容量小 读写速度一般读取速度快 断电后数据永久存储断电后数据清空 三、硬盘数据为什么要读取到内存&#xff1f;为啥不直接…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...