web worker实现xx分钟不操作后,页面失效

预设条件

  • 静默时长:10分钟;
  • 页面失效,返回首页
  • 10分钟内有操作,则重新计时
  • 同一表单页,仅支持唯一一方操作,其他方预操作

实现思路

10分钟的统计通常情况下会使用setInterval(),但是由于setInterval()计时会有一定误差,设置在浏览器处于非激活状态下可能会以极慢的速度工作甚至停止计时,因此,本文采用web worker新建线程来准确计时。

Web Worker

Web Worker:HTML5标准的一部分,允许我们在js主线程之外开辟新的一个线程,并且将一段js脚本运行其中,使其与主线程同步进行,互不阻塞。所以,目前很多在js主线程只专注处理业务逻辑,Worker线程负责计算等复杂任务,提高运行效率、页面流畅度等。

注意

  • Worker 线程中不可操作DOM对象、不可访问window对象;

  • Worker 的顶层对象:self

  • 使用:new Worker(path, options)

    • path:有效的js脚本地址(遵守同源策略)
  • 关闭Workerworker.terminate()

  • postMessage()传递的数据支持:由结构化克隆算法处理的任何值或JS对象,包括循环引用。

实现方法

  1. public 文件夹下,新建Worker.js文件
js 复制代码
// 监听 接收消息
let timer;
self.addEventListener('message', e => { // 接收到消息
    console.log(e.data); 
    
    let sum = 0;
    let msg;
    
    if (e.data === "start") {
        // 每分钟 sum 加 1 标识积累了 1 分钟
         timer = setInterval(() => {
            sum += 1;
            msg = {
                text: 'editing',
                sum
            }
            // 向主线程发送消息 msg 对象
            self.postMessage(msg); 
         }, 60 * 1000) 
    } else {
        clearInterval(timer);
    }
});


// worker内部错误
self.addEventListener('error', err=>{
    cosole.log(err)
})
// 消息体无法被反序列化时
self.addEventListener('messageError', err=>{
    cosole.log(err)
})
  1. Vue组件中创建并使用Worker.js
js 复制代码
<template>
    <el-form>
        ...表单内容
    </el-form>
<template>

<script>
export default {
    data:_=>({
        worker: null
    }),
    created() {
        this.startWorker();
    },
    activated() {
        this.onTimerReset()
    },
    methods: {
        // 开启worker
        startWorker() {
           // 判断浏览器兼容性
           if(typeof Worker !== 'undefind') {
                // 创建Worker实例
                this.worker = new Worker('./Worker.js');
                this.handleWorker()
            } else {
                console.log('Your browser does not support Web Workers.')
            } 
        },
        stopWorker() {
            if(this.worker) {
                this.worker.terminate();
                this.worker = null;
            }
        },
        handleWorker() {
            const selfWorker = this.worker
            selfWorker.postMessage('start timer')
            
            // 监听 来自 worker的 message 消息
            selfWorker.onmessage = e => {
                this.handleWorkerMsg(e.dada)
            }
        },
        // 开启计时
        onTimerSatrt() {
            this.worker.postMessage('start timer')
        },
        // 关闭计时
        onTimerEnd() {
            this.worker.postMessage('start end')
        },
        // 重新计时
        onTimerReset() {
            this.onTimerEnd()
            this.onTimerSatrt()
        },
        // 处理数据
        handleWorkerMsg(data) {
            console.log(data); // {text: 'editing', sum: sum} 
            campaignListLock(); // 发起续租请求
            
            if(data.sum >10) {
                this.onTimerEnd();
                if (document.visibilityState === "visible") { 
                    message.error("页面已失效"); 
                    pageGoBack(); 
                    // 触发了提示就禁止它后续再触发 
                    timeCount = 1;
                } 
                document.addEventListener("visibilitychange", function () { 
                    if (document.visibilityState == "visible" && timeCount == 0) { 
                        message.error("页面已失效"); 
                        pageGoBack(); 
                        // 触发了提示就禁止它后续再触发
                        timeCount = 1; 
                    }
                });
            }
        },
    },  
    beforeDestroy() {  
        // 在组件销毁前停止 Worker,避免内存泄漏  
        this.stopWorker();  
    },  
}
</script>
相关推荐
Мартин.2 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。3 小时前
案例-表白墙简单实现
前端·javascript·css
数云界3 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd3 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常3 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer3 小时前
Vite:为什么选 Vite
前端
小御姐@stella3 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing3 小时前
【React】增量传输与渲染
前端·javascript·面试
eHackyd4 小时前
前端知识汇总(持续更新)
前端
万叶学编程7 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js