js Worker解决ios下面倒计时手滑问题

2103次浏览

前言

倒计时我们经常用。之前我也有很多文章提及过。例如:setTimeout倒计时等等。最近在移动端开发过程中,遇到一个ios手机滑动,倒计时卡住的问题,针对这个问题,我们可以用js的Worker。

倒计时案例

用setInterval写的最基本的倒计时,代码如下:

<body>

    <div id="haorooms">60</div>

    <script>

    var haorooms = document.getElementById('haorooms');
    var num = 60;

    var T = setInterval(function(){

        haorooms.innerHTML = --num;
        if(num <= 0){
            clearInterval(T);
        }

    }, 1000);

    </script>
</body>

这段代码在PC中可以正常运行,在Android中也可以正常运行,但是拿到ios中,就会有一个问题,来看图:

enter image description here

上图中,当倒计时走到37的时候,用手拖动页面,这个时候js代码会被阻塞,导致倒计时不在执行。

针对这个问题,只能用我们上文中提及的Worker API了。

Worker API

Web Workers API 的 Worker 接口代表一个可以轻松创建的后台任务,并可以将消息发送回其创建者。创建一个工作程序只要简单的调用Worker() 构造函数,并指定一个要在工作线程中运行的脚本。

worker 还能够使用 XMLHttpRequest 实现网络 I/O 操作, 只不过 XMLHttpRequest 上的 responseXML 与 channel 两个属性值始终返回 null。

2个方法

1、postMessage()

向 worker 的内部作用域内传递消息。该方法接收一个单独的参数,即要传递给 worker 的数据。

void postMessage( Object aMessage [, sequence<Transferable> transferList]);

参数:

aMessage

传输给 worker 的对象;它将包含于传递给 onmessage 处理函数的事件对象中的 data 字段内。你可以传递任意值或是经过结构化拷贝算法处理过的 JavaScript 对象,即可以包含循环引用。

transferList

一个可选的对象数组,用于转让它们的所有权。如果一个对象的所有权被转让,那么它在原来的上下文内将不可使用,而只能在转让到的 worker 内可用。

2、terminate()

立即终止 worker。该方法不会给 worker 留下任何完成操作的机会;就是简单的立即停止。

解决方案

我们的思路是,将倒计时的计算放到一个单独的文件里,使用 Worder 去执行这个文件。

新建一个 countdown.js 文件:

self.onmessage = function(event){
    var num = event.data;

    var T = setInterval(function(){

        self.postMessage(--num);
        if(num <= 0){
            clearInterval(T);
            self.close();
        }

    }, 1000);
}

由于这个js文件是由 Worker 来在后台执行的文件,所以这个文件内代码的 self 指向的就是 Worker 对象。我们通过 onmessage 时间接收来自页面的倒计时数值,然后原封不动的把之前的倒计时代码拷贝过来,唯一不同的就是使用 self.close() 语句来关闭 Worker。

然后修改之前的页面文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>倒计时</title>
</head>
<body>
    <div id="haorooms">60</div>

    <script>
    var haorooms = document.getElementById('haorooms');
    var w = new Worker('counter.js');
    w.postMessage(60);
    w.onmessage = function(event){
        haorooms.innerHTML = event.data;
    }

    </script>
</body>
</html>

在PC中刷新你的页面,可以看到依然正确工作,之后再拿到ios中做之前gif图同样的操作,如下图:

enter image description here

我们可以看到,在55秒的时候开始拖动页面,这个时候倒计时停止了,不过,当我们放手之后,倒计时会立刻恢复到正常应该到达的时刻,而不会产生任何误差和延迟,这样,我们就比较完美的解决了这个问题。

注意

上面的Worker代码必须在localhost等环境下面运行,因为上面提及过,它用到了XMLHttpRequest。

关于Worker更多API,请查看:https://developer.mozilla.org/en-US/docs/Web/API/Worker

中文版可以看:https://developer.mozilla.org/zh-CN/docs/Web/API/Worker

部分资料同事提供,来源已无法考究作者。

Tags: jsworker

相关文章: