实现功能是要在一个文件列表的右侧操作区加一个验证md5的按钮,用来验证每个上传的文件的完整性,刚开始实现的思路是:点击按钮,触发checkMd5接口请求,后端用异步的方式将文件从服务器下载下来并生成md5值,将该值与前端md5值进行对比,一样则操作数据库md5Status字段为1,不一样则为0;前端设置函数checkStatus(imageId),该函数中用到setInterval定时器每隔2秒不停调用checkStatus接口查看md5Status值,直到如果该值(在进行验证前会设置为正在验证中,状态值变为2)变化为0或者1就停止checkStatus请求。如下为checkStatus()函数代码:
checkStatus: function(id){
var _this = this;
_this.refreshTimer = setInterval(function(){
ImageApi.checkStatus({id:id}).then(function (res){
if(res === 0 || res === 1){
if(res === 0){
_this.$notification['success']({
message: '校验失败',
description: '文件MD5码不正确',
duration: 4
});
}else {
_this.$notification['success']({
message: '校验成功',
description: '文件完整',
duration: 4
});
}
console.log('timer',_this.refreshTimer);
clearInterval(_this.refreshTimer);
_this.refreshTimer = null;
console.log('clear',id);
_this.$refs['image_table'].refresh();
}
})
}, 2000);
}
测试中出现的问题是:点击一次正常,但如果依次连点两个镜像按钮进行验证,则会不停的出现校验成功的弹框,也就是即使md5Status状态值已经变化仍在不停的发送请求,如下:
原因:用console.log(_this.refreshTimer)可以看出这个refreshTimer不是定时器本身,它只是一个用于传递定时器ID的返回值,连点两个镜像的验证按钮,每一次给refreshTimer赋值都是在创建新的定时器对象,就会造成定时器累加,但是refreshTimer只会存储最新创建的定时器ID,当先请求到状态值变化(镜像文件越大,后台验证的越慢)的定时器代码会进去执行clearInterval(_this.refreshTimer); _this.refreshTimer = null;对最新的那个定时器进行清除并设为null,但之前的定时器并没有被清除,所以当后一个请求到变化时调用clearInterval()却已经找不到他的refreshTimer了,无法清除,就造成了不断代码执行的情况。
解决办法:控制每次只有一个定时器在使用,使用完被清除后再允许创建下一个定时器。