Web Worker实现倒计时

项目场景:

vue项目完成一个倒计时


问题描述

当离开存在倒计时的标签页时,出现倒计时不准确的情况


原因分析:

当进入其他页面时,浏览器会延缓原页面的定时器的执行


解决方案:

利用Web Worker在主线程外再开一个线程用来处理定时器数据
用法:

<CountdownTimer :initialTime= deadline @finish="onFinish" />

timerWorker.js

let remainingTime;

self.onmessage = function (e) {
  if (typeof e.data === "number") {
    remainingTime = e.data;
    updateTimer();
  }
};

function updateTimer() {
    if (remainingTime > 0) {
      postMessage(remainingTime); // 发送剩余时间到主线程
      remainingTime--;
      setTimeout(updateTimer, 1000); // 每秒更新一次
    } else {
      postMessage(remainingTime); // 确保在时间为 0 时发送消息
    }
}

countdownTimer.vue

<template>
  <div class="time">
    <div>{{ time }}</div>
  </div>
</template>

<script setup>
import { ref, onUnmounted, watch } from "vue";

const props = defineProps({
  initialTime: {
    type: Number,
    required: true,
  },
});

const emit = defineEmits(["finish"]);
const remainingTime = ref(props.initialTime);
const time = ref(msToTime(remainingTime.value));
let timerWorker = null;

const startWorker = (initialTime) => {
  if (window.Worker) {
    timerWorker = new Worker(
      new URL("../config/timerWorker.js", import.meta.url)
    );
    timerWorker.onmessage = (e) => {
      if (typeof e.data === "number") {
        remainingTime.value = e.data;
        time.value = msToTime(remainingTime.value);
        if (remainingTime.value === 0) {
          emit("finish");
        }
      }
    };

    timerWorker.postMessage(initialTime);
  } else {
    console.log("doesn't support Web Workers");
  }
};

watch(
  () => props.initialTime,
  (newInitialTime) => {
    if (newInitialTime > 0) {
      remainingTime.value = newInitialTime;
      time.value = msToTime(remainingTime.value);
      startWorker(newInitialTime);
    }
  },
  { immediate: true }
);

onUnmounted(() => {
  if (timerWorker) {
    timerWorker.terminate();
  }
});

function msToTime(duration) {
  let seconds = Math.floor(duration % 60),
    minutes = Math.floor((duration / 60) % 60),
    hours = Math.floor((duration / (60 * 60)) % 24);

  hours = hours < 10 ? "0" + hours : hours;
  minutes = minutes < 10 ? "0" + minutes : minutes;
  seconds = seconds < 10 ? "0" + seconds : seconds;
  return hours + ":" + minutes + ":" + seconds;
}
</script>

<style  lang="less" scoped>
.time {
  color: #c9353f;
  font-weight: 600;
  font-family: unset;
  font-size: 1.25rem;
  line-height: 1.66667rem;
}
</style>

你可能感兴趣的:(前端,javascript)