ArcGIS JSAPI 学习教程 - JavaScript 子线程基础示例

在这里插入图片描述

本文主要介绍一下 JavaScript 子线程教程。

JavaScript 为单线程,因此在执行代码过程中遇到耗时操作,会导致页面卡顿。

而子线程就是为了解决这个问题,将耗时任务交给子线程去执行,主线程与子线程通信,获取任务结果,再进行后续工作即可。

需要注意的是,子线程不能操作 dom,原因为防止DOM的复杂渲染操作导致的数据冲突,具体可搜索或者 AI 一下。

本文包括 完整代码以及在线示例


完整代码

简单设计了一个子线程示例,大概过程为,计算斐波那契数,并且利用 canvas 动态展示卡顿效果。

一种是主线程计算,主线程被占用时,canvas 小球停止移动

而子线程计算时,主线程几乎不受影响,canvas 小球不会停止移动


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"/>
    <title>Web Worker 示例</title>
</head>
<body>
<span>计算第</span><input id="fibonacci" value="40"/><span>项斐波那契数</span>
<button onclick="startCompute()">开始计算</button>
<button onclick="startWorker()">开始计算(使用Worker)</button>
<button onclick="stopWorker()">停止Worker</button>
<div id="waiting"></div>
<div id="time"></div>
<div id="result"></div>

<canvas id="animationCanvas" width="600" height="300" style="padding-top: 5px;"> </canvas>

<script>

    // 初始化动画小球
    bounceBall();

    let worker;

    // 计算斐波那契数列(模拟耗时任务)
    function fibonacci(n) {
        if (n <= 1) return n;
        return fibonacci(n - 1) + fibonacci(n - 2);
    }

    // 初始化等待HTML
    function initWaitingHtml() {
        document.getElementById("waiting").innerHTML = `正在计算,请稍等...`;
        document.getElementById("time").innerHTML = ``;
        document.getElementById("result").innerHTML = ``;
    }

    // 初始化结果HTML
    function initResultHtml(data, timeStart) {
        document.getElementById("result").innerHTML =
            `斐波那契结果: ${data}`;
        document.getElementById("waiting").innerHTML = ``;
        document.getElementById("time").innerHTML = `计算耗时: ${performance.now() - timeStart} 毫秒`;
    }

    // 启动Worker
    function startWorker() {
        if (typeof Worker !== "undefined") {

            initWaitingHtml();

            worker = new Worker('./workersFolder/worker.js'); // 创建Worker

            const timeStart = performance.now();

            // 接收Worker结果
            worker.onmessage = function (event) {
                initResultHtml(event.data, timeStart);
            };

            // 错误处理
            worker.onerror = function (error) {
                console.error(`Worker错误: ${error.filename} (行: ${error.lineno})`);
            };

            const fibonacciNum = parseInt(document.getElementById("fibonacci").value);

            // 发送计算任务(计算第40项斐波那契数)
            worker.postMessage(fibonacciNum);
        }
    }

    // 开始计算
    function startCompute() {

        const fibonacciNum = parseInt(document.getElementById("fibonacci").value);

        initWaitingHtml();

        const timeStart = performance.now();

        const result = fibonacci(fibonacciNum); // 执行计算

        initResultHtml(result, timeStart);
    }

    // 终止Worker
    function stopWorker() {
        if (worker) {
            worker.terminate(); // 释放资源
            worker = null;
            console.log("Worker已终止");
        }
    }

    // 初始化动画小球
    function bounceBall() {

        const canvas = document.getElementById("animationCanvas");
        const ctx = canvas.getContext("2d");
		
        // 初始化圆的属性
        let x = 50; // 圆心的x坐标
        let y = 160; // 圆心的y坐标
        let radius = 20; // 圆的半径
        let dx = 2; // x方向的速度
        let dy = 1; // y方向的速度

        // 绘制圆的函数
        function drawCircle() {
            ctx.beginPath(); // 开始一条新路径
            ctx.arc(x, y, radius, 0, Math.PI * 2, false); // 绘制圆
            ctx.fillStyle = 'blue'; // 设置填充颜色为蓝色
            ctx.fill(); // 填充圆
			
			// 设置边框样式
			ctx.strokeStyle = 'red'; // 边框颜色
			ctx.lineWidth = 3; // 边框宽度
			ctx.strokeRect(0, 0, canvas.width, canvas.height);
			
            ctx.closePath(); // 结束路径的绘制
        }

        // 动画函数
        function animate() {
            ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
            drawCircle(); // 绘制圆
            x += dx; // 更新x坐标
            y += dy; // 更新y坐标
            if (x + radius > canvas.width || x - radius < 0) { // 如果圆碰到边界,改变方向
                dx = -dx; // 改变x方向的速度
            }
            if (y + radius > canvas.height || y - radius < 0) { // 如果圆碰到边界,改变方向
                dy = -dy; // 改变y方向的速度
            }
            requestAnimationFrame(animate); // 递归调用animate函数,实现动画效果
        }
        // 开始动画
        animate();
    }

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

在这里插入图片描述


在线示例

ArcGIS Maps SDK for JavaScript 在线示例:JavaScript 子线程基础示例

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐