React | Memory Leak

内存泄漏问题想必大家够遇见过,但是怎么才能去预防或者说遇到的时候怎样去处理呢?

什么是内存泄漏

程序在运行时候需要操作系统为其分配内存。对于持续运行的服务进程(daemon),必须及时释放不再用到的内存,轻则影响系统性能,重则导致进程崩溃。

有些语言(比如 C 语言)必须手动释放内存,程序员负责内存管理。

char * buffer;
buffer = (char*) malloc(42);

// Do something with buffer

free(buffer);

上面是 C 语言代码,malloc方法用来申请内存,使用完毕之后,必须自己用free方法释放内存。

这很麻烦,所以大多数语言提供自动内存管理,减轻程序员的负担,这被称为"垃圾回收机制"(garbage collector)

在这里插入图片描述
参考《JavaScript 内存泄漏教程》

js常见的内存泄漏
  • 全局变量引起的内存泄漏
function leaks(){  
    leak = '***'; //leak 成为一个全局变量,不会被回收
}
  • 闭包引起的内存泄漏
var leaks = (function(){  
    var leak = '***';// 被闭包所引用,不会被回收
    return function(){
        console.log(leak);
    }
})()
  • dom清空或删除时,事件未清除导致的内存泄漏
document.querySelector("#demo").addEventListener('click', myFunction);

var para1=document.querySelector("#demo");

para1.parentNode.removeChild(para1);

如果我们在没有取消 click 方法前去销毁了 para1 节点,就会造成内存泄露。

正确做法
document.querySelector("#demo").addEventListener('click', myFunction);

// 我们需要在删除节点前清除挂载的 click 方法
document.querySelector("#demo").removeEventListener("click", myFunction);

var para1=document.querySelector("p1");

para1.parentNode.removeChild(para1);
例子:

在这里插入图片描述
关键代码:

子组件

class StoreCard extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            loading: true
        }
    }
    componentDidUpdate() {
        this.state.loading = true;
    }
    render() {
        const dataAll = ClassStore[this.props.data.key].data[this.props.data.item].dataAll;
        //...............................注意...........................
        setTimeout(e => {
            this.state.loading = false
            this.forceUpdate();
        }, 1000)
        //...............................注意...........................
        return dataAll.length ? <PageData data={dataAll} loading = {this.state.loading} />:<Empty description={false} />
    }
}
export default StoreCard;

父组件:

//省略.............................................................
.........................................
const routeMap = {}
const currentPage = document.location.hash.replace(/#\/?/, "");
const CurrentPage = routeMap[currentPage] || StoreCard;
........................................................
//引用子组件
function SiderPage(props) {
    return (
        <Layout style={{ padding: '0 24px 24px' }}>
            <Content
                style={{
                    background: '#fff',
                    padding: 24,
                    margin: 10,
                    minHeight: 280,
                }}
            >

                <CurrentPage data={props.data} />
            </Content>
        </Layout>
    );
}
//省略............................................................

//存在一个页面跳转
function HeaderIndex() {
    return (
        <Header className="header">
            <div className="title-logo">
                ..............................................................
                        <Menu.Item key="1">
                            <Link to="/login">你好!请登录 </Link>
                        </Menu.Item>
                        <Menu.Item key="2">免费注册</Menu.Item>
             ..............................................................................
        </Header>
    );
}
原因:因为子组件之中存在一个settimeout,并没有在组件卸载前被清除,这个时候导致内存泄漏而报错…

解决办法:

在卸载之前清除settimeout

class StoreCard extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            loading: true
        }
    }
    componentDidUpdate() {
        this.state.loading = true;
    }
    //..............................增加...........................
    componentWillUnmount(){
        clearTimeout(this.loadTime);
    }
    //...............................增加..........................
    render() {
        const dataAll = ClassStore[this.props.data.key].data[this.props.data.item].dataAll;
        //...............................修改...........................
        this.loadTime = setTimeout(e => {
            this.state.loading = false
            this.forceUpdate();
        }, 1000)
        //...............................修改...........................
        return dataAll.length ? <PageData data={dataAll} loading = {this.state.loading} />:<Empty description={false} />
    }
}
export default StoreCard;

成功解决!!!

扩展: Chrome 怎样去识别内存泄漏

在这里插入图片描述
在这里插入图片描述

扩展阅读

1、《promise 请求是否会造成内存泄露》Does never resolved promise cause memory leak?
Does never resolved promise cause memory leak?

2、《循环一个 promise 造成内存泄露?》Memory leaks in loops with Promise ?
3、《常见setState的原理解析》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值