弹框不影响定时器的继续执行

因为 js 为单线程语言,所以在一般情况下,当弹框出现时,定时器是必定会停止的,如以下实例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>土狗一号</title>
</head>
<body>
    <div></div>
    <button>弹框</button>
    <script>
        var div = document.body.children[0]
        var test = 100
        // 简单的定时器,让倒数继续
        setInterval(function (){
            test -= 1
            div.innerHTML = test
        }, 1000)
        var button = document.body.children[1]
        button.onclick = function (){
            alert("test")
        }
    </script>
</body>
</html>

为了做到弹出弹框也让递减继续,必须要在js中使用多线程
需使用H5中提供的Web Worker对象

什么是Web Worker?

当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。
web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行。

也就是说,我们可以使用 web worker 创建一个实例,通过这个实例调用外部 JS。
这个外部 JS 此时正运行在后台,即使主页面出现了弹框,也不会影响后台的进程。

接下来我们对上面的例子进行改写:

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>土狗一号</title>
</head>
<body>
    <div></div>
    <button>ss</button>
    <script>
        // 创建实例,括号内跟路径
        var worker1 = new Worker('./test.js')
        var div = document.body.children[0]
        // 向 web worker 添加一个 "onmessage" 事件监听器
        // 箭头函数获得的 e.data 为 js 文件中 self.postMessage()返回的值
        worker1.onmessage = e => {
            // 把 js 文件中拿到的值赋给 div
            div.innerHTML = e.data
        }
        /*
        *   上面的操作就是把 js 中拿到的值赋给 div
        */
        var button = document.body.children[1]
        button.onclick = function (){
            alert("test")
        }

         // 在 HTML 关闭脚本
        // worker1.terminate()
    </script>
</body>
</html>

JS:

var test = 100
    // 设置定时器,每过一秒执行一次
    self.setInterval(function(){
        test -= 1
        // 将拿到的值传给 HTML 页面
        self.postMessage(test)
        // 如果 test 走到0则 Worker 关闭自身,也就是停止运行该文件
        if(test == 0){
            // 在 Worker 内部关闭自身,如想在 HTML 中关闭则需用其他方法
            self.close()
        }
    }, 1000)

:最好部署在服务器上进行此操作(IE 某些版本也可以)否则可能会出现以下错误

由于谷歌的安全机制,此操作会被当做跨域......不允许在本地直接运行

但此方法有个很大的缺点!!!

因为 JS 本为单线程语言,所以上述代码的执行效率并不高,甚至可以说是很低...
在运行上述案例的时候就会发现,当点开弹窗后,数字递减的显示是有卡顿的。
但如果把弹窗关闭,卡顿则会消失(递减的次数不会受卡顿影响)
因此,在选用本方法时,一定要考虑应用场景。

posted @ 2020-10-25 17:35  土狗一号  阅读(262)  评论(0)    收藏  举报