省流版本
当前页面所处的标签页关闭后,WebWorker会被强制关闭。
如果一直在一个标签页内,需要使用terminate()函数手动关闭WebWorker
页面功能
今天遇到了一个很神奇的BUG,在此记录一下。
一共有两个页面,一个“详情”,一个“采购单”,其中“采购单”需要从详情页面的“编辑采购单”按钮进入,是使用新标签页打开的方式进入的
当有用户进入采购单后,会立刻记录一个时间,并开始执行一个60秒一次的定时器,每60秒会调用API记录一次时间。
当详情里有另一个用户点击“编辑采购单”,如果当前时间和记录时间之差<1分钟,则无法进入(避免有两个人在同时编辑一个采购单)
定时器的代码是:
/// <reference lib="webworker" />
addEventListener('message', ({ data }) => {
const timer = setInterval(() => {
data += 1;
postMessage(data);
}, 1000);
});
采购单中执行定时器代码是:
const w = new Worker('./purchase-timer.worker', { type: 'module' });
w.postMessage(0);
w.onmessage = ({ data }) => {
if (data % 60 === 0) {
this.devManageService.postTickTime({
pre_products_id: this.planId,
op_date1: moment(new Date()).format('YYYY-MM-DD HH:mm:ss'),
op_date1_user_id: this.general.getUserId()
}).subscribe(res => { });
}
};
BUG描述
产品给我描述的BUG是:“他们有人退出了采购单,并且也保证没有页面处于采购单里,但其他人还是进不去,提示的弹窗里时间一直在增加”
咱们是无神论者,要相信科学相信程序,肯定不得有什么脏东西!
于是我亲自去页面实验了一下,发现并不会出现这样的BUG,在我纳闷的时候,产品成功复现了BUG情况,并叫我过去看。
看了之后我终于发现了问题所在:我返回详情的方式是直接关闭的标签页(因为采购单是新标签页嘛),而部分人的习惯是点击返回按钮回到详情页,这样就会导致虽然离开的采购单,但标签页依旧存在,定时器并不会关闭。
所以解决办法就很简单,当返回的时候手动关闭定时器即可。
解决办法
因为我的定时器只是在进入页面,ngOnInit周期的时候调用,是一个常量,无法在返回按钮中关闭,所以我设定了一个函数isOut去判断用户是否已经退出采购单页面。
在定时器的调用函数中,每次调用时根据isOut判断是继续计时,还是直接关闭计时器就可以了
修改后的代码为:
const w = new Worker('./purchase-timer.worker', { type: 'module' });
w.postMessage(0);
w.onmessage = ({ data }) => {
if (data % 60 === 0 && !this.isOut) {
this.devManageService.postTickTime({
pre_products_id: this.planId,
op_date1: moment(new Date()).format('YYYY-MM-DD HH:mm:ss'),
op_date1_user_id: this.general.getUserId()
}).subscribe(res => { });
} else {
w.terminate();
}
};