Notes for a front-end developer, esyou.net

0%

使用SETTIMEOUT出现内存溢出的解决办法

setTimeout就是一个定时器,它可以很容易地实现在规定时间内所要执行的函数或方法。但是我再setTimeout的使用过程中就出现了内存溢出的各种问题。下面我将使用一个当前时间与过去的某个时间差的计算方式来进行讲解setTimeout,首先来看逻辑思想部分。
对于任何编程语言,我们刚开始都需要进行需求分析,需求分析就是一个实现功能的想法或者步骤。
比如我在这个例子中将会使用本地当前时间减去我所获得的时间,得到它们之间的时间差。

获得当前时间

获得当前时间可以直接使用new Date(),即可获得当前本地或者说本机时间。
目前已知时间为:2017-05-20 00:29:10

如何对时间进行相减

其实在JavaScript中,时间是可以直接进行减法运算的,不过必须是JavaScript的Date日期格式,如果是其他的则不支持,比如我们直接使用2017-05-20 00:29:10 - 2017-05-20 00:28:10,这样的相减是会报错的。而且也是无法相减的,因为他们两个是字符串,无法进行相减。那该怎么办?
很简单,我们将2017-05-20 00:29:10转换为Date对象即可。而JavaScript的Date对象得到的日期格式应该是这样的“Sat May 20 2017 00:33:26 GMT+0800”,我们可以通过new Date()对我们上面的字符串“2017-05-20 00:29:10”进行转换,但是转换之前必须将此字符串,转换为如下格式“2017/05/20 00:29:10”,这样的格式才能被JavaScript的Date()识别。
如此一来,他们就可以进行相减了。

相减后获得的秒数该如何计算?

两个日期相减得到的是毫秒数,根据1000毫秒=1秒的计算方式,我们可以得到要将毫秒转换为秒,我们需要将当前的毫秒数除以(100060)再乘以60,由此可以得到公式(毫秒/(100060)*60就可以得到秒数)。

在页面上实时显示秒数

这里就进入了我们今天的正题了,使用setTimeout定时器即可实现,其用法setTimeout(code,time),其中code是即将执行的代码,time为执行的毫秒数。

使内存溢出的setTimeout

从上面的分析我们很容易就可以得出相关代码,代码如下:

1
function myDate(){
2
    var localDate = new Date();
3
    console.log(localDate);
4
    var include_date=('2017-05-19 21:23:01').replace(/-/g,"/");
5
    var crawler_date = new Date(include_date);
6
    var time_difference = Math.ceil((localDate-crawler_date)/(1000*60)*60);
7
    console.log(time_difference);
8
    document.getElementById("m").innerHTML = time_difference+'秒'
9
}
10
setTimeout(myDate(),1000);

经过我的经验告诉我,执行了以上代码后,这些代码并不会定时的去执行myDate(),那么是上面原因导致了这个错误?是不是代码写错了,还是分析的不对?
最终我确定了,setTimeout(“myDate()”,1000);必须要放在函数内,才会生效,否则他将仅执行一次,而放在函数内就会根据我们设定的时间去执行相关方法。因此正确的代码应该是这样的

1
function myDate(){
2
    var localDate = new Date();
3
    console.log(localDate);
4
    var include_date=('2017-05-19 21:23:01').replace(/-/g,"/");
5
    var crawler_date = new Date(include_date);
6
    var time_difference = Math.ceil((localDate-crawler_date)/(1000*60)*60);
7
    //return time_difference;
8
    console.log(time_difference);
9
    document.getElementById("m").innerHTML = time_difference+'秒'
10
    setTimeout(myDate(),1000);
11
}
12
myDate()

但是我的天啊,这段代码竟然让我的内存溢出了,而且超级占内存,浏览器都会卡死!你可以通过console.log()来查看执行的效果,你应该会看到如下执行效果,你会发现我靠,每一秒都执行超级多的次数!

这是不是传说中浏览器傻逼了,还是JavaScript傻逼了?
我使用了clearTimeout也无法解决这个问题,在网上也没有查到相关解决方法。不过我看到一个实例,他的代码中是这样使用setTimeout的setTimeout(“code”,time);,看到了吧,在执行的代码外增加了双引号,这是什么鸟?为什么要这样使用?这个原因我也不得而知,但是这确实让我解决了内存溢出的问题。最终代码如下:

1
function myDate(){
2
    var localDate = new Date();
3
    //console.log(localDate);
4
    var include_date=('2017-05-19 21:23:01').replace(/-/g,"/");
5
    var crawler_date = new Date(include_date);
6
    var time_difference = Math.ceil((localDate-crawler_date)/(1000*60)*60);
7
    //return time_difference;
8
    console.log(time_difference);
9
    document.getElementById("m").innerHTML = time_difference+'秒'
10
    setTimeout("myDate()",1000);
11
}

执行后出现如下正常的浏览器反馈了:

到此我们确实可以说在原生JavaScript中,我们解决了这个内存溢出的问题,但是问题又来了,我再VUE中这样去使用setTimeout又出问题了。

VUE中使用setTimeout

1
methods:{
2
    myDate(){
3
        let localDate = new Date();
4
        let include_date=(this.data).replace(/-/g,"/");
5
        let crawler_date = new Date(include_date);
6
        let time_difference = Math.ceil((localDate-crawler_date)/(1000*60)*60);
7
        //return time_difference;
8
        this.time = time_difference
9
        //console.log(time_difference);
10
        if(time_difference>60){
11
          this.style='background-color:red;color:#FFF'
12
      }else if(time_difference>0 && time_difference<60){
13
          this.style='background-color:blue;color:#FFF'
14
      }else{
15
          this.style='color:#000'
16
      }
17
      setTimeout(this.myDate(),1000);
18
    }
19
}

如果你直接使用以上代码去执行那么我们又回到了之前的内存溢出的问题上了,如果你将setTimeout(this.myDate(),1000);修改为setTimeout(“this.myDate()”,1000);那么VUE肯定报错说找不到myDate(),或者myDate()并不是函数。我靠,这样一来该如何解决这个问题?
在折腾了一番之后,我得到了相关解决方法。
原来在VUE中,调用方法,如果方法中没有传递任何参数的话,我们直接使用函数的名称即可,无需增加“()”,由此就可以得到最终的代码了:

1
methods:{
2
    myDate(){
3
        let localDate = new Date();
4
        let include_date=(this.data).replace(/-/g,"/");
5
        let crawler_date = new Date(include_date);
6
        let time_difference = Math.ceil((localDate-crawler_date)/(1000*60)*60);
7
        //return time_difference;
8
        this.time = time_difference
9
        //console.log(time_difference);
10
        if(time_difference>60){
11
            this.style='background-color:red;color:#FFF'
12
        }else if(time_difference>0 && time_difference<60){
13
            this.style='background-color:blue;color:#FFF'
14
        }else{
15
            this.style='color:#000'
16
        }
17
        setTimeout(this.myDate,1000);
18
    }
19
}

看到setTimeout中内容的变化了吧!这样就能够真正实现定时器了!
setTimeout真是变化多端,我们得根据不同的环境进行不同的使用,才能实现我们想要的定时器效果。