web worker实现倒计时
emer 发布于 2023-1-29 18:54 824 次阅读
<CountDownTimer endTime={1569834068266} onEnd={this.onEndHandler.bind(this)} />
CountDownTimer.jsx
import React from "react"; import styled from "styled-components"; import WebWorker from "../../utils/worker"; let work = function() { let timer = null; this.onmessage = e => { const { endTime, state } = e.data; if (state === "stop") { if (timer) { clearInterval(timer); timer = null; } return; } else if (state === "start") { let interval = 1000; if (!timer) { timer = setInterval(() => { this.postMessage(endTime - new Date().getTime()); }, interval); } } }; }; let worker = new WebWorker(work); /** * 计算相对时间字符串 * @param {number} time 13位时间戳 */ function relativeTime(time) { if (time <= 0) { return "00:00"; } const minute = Number.parseInt(time / 1000 / 60, 10); const second = Number.parseInt((time / 1000) % 60, 10); return `${minute > 9 ? minute : "0" + minute}:${ second > 9 ? second : "0" + second }`; } export default function CountDownTimer({ endTime, onEnd = Function.prototype }) { const initTime = relativeTime(endTime - new Date().getTime()); let [time, setTime] = React.useState(initTime); worker.onmessage = e => { if (e.data <= 0) { worker.postMessage({ state: "stop" }); return; } setTime(relativeTime(e.data)); }; React.useEffect(() => { worker.postMessage({ state: "start", endTime: Number.parseInt(endTime, 10) }); return function() { worker.postMessage({ state: "stop" }); }; }, [endTime]); React.useEffect(() => { if (time === "00:00") { return function() { onEnd(); worker.postMessage({ state: "stop" }); }; } }, [time, endTime, onEnd]); const Time = styled.span` font-size: 1.6rem; font-weight: 700; vertical-align: middle; `; return ( <div> 倒计时:<Time>{time}</Time> </div> ); }
worker.js
export default class WebWorker { constructor(worker) { const code = worker.toString(); const blob = new Blob([`(${code})()`]); return new Worker(URL.createObjectURL(blob)); } }