You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何持续调用异步函数展示卫星位置及多场景switch case实现方案

问题修复与多场景适配方案

原有代码存在的问题

  • 逻辑高度重复,两套渲染逻辑仅图标、挂载容器两个参数存在差异,维护成本高
  • 未存储定时器ID,切换展示模式时无法清除旧定时器,会导致重复请求、内存泄漏
  • 未销毁旧地图实例,多次切换会导致多个地图实例同时占用DOM资源,引发卡顿
  • a标签未阻止默认跳转行为,点击会触发页面刷新,逻辑无法正常执行
  • 状态变量(首次定位标记、标记实例、地图实例)定义在函数内部,全局无法访问,无法实现状态复用与清理

修复实现步骤

1 调整HTML结构

给所有切换链接增加自定义属性标记展示类型,统一绑定点击事件,阻止默认跳转:

<h1>Where is the ISS?</h1>
<p>
    latitude: <span id="lat"></span>°<br>
    longitude: <span id="lon"></span>°
</p>
<div>
    <a class="link" data-type="1" href="javascript:void(0)">带图标展示</a>|
    <a class="link" data-type="2" href="javascript:void(0)">无图标展示</a>|
    <a class="link" data-type="3" href="javascript:void(0)">后续新增选项</a>
</div>
<!-- 仅保留一个地图容器即可,不需要多个 -->
<div id="issMap"></div>

2 重构JS逻辑

将公共变量全局存储,封装通用渲染函数,用配置表处理多场景差异,切换前自动清理旧资源:

// 全局公共变量存储
let mapInstance = null;
let markerInstance = null;
let updateTimer = null;
let isFirstLocation = true;
const apiUrl = 'https://api.wheretheiss.at/v1/satellites/25544';
const attribution = '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
const tileUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';

// 多场景配置表,新增场景仅需在这里加配置即可,无需修改核心逻辑
const renderConfig = {
    1: {
        icon: L.icon({
            iconUrl: "iss200.png",
            iconSize: [75, 75],
        })
    },
    2: {
        icon: null
    },
    3: {
        // 后续新增场景配置,比如其他卫星图标、不同刷新频率、不同地图层级等
        icon: L.icon({
            iconUrl: "other-satellite.png",
            iconSize: [50, 50],
        })
    }
}

// 清理旧资源通用函数
function clearOldResource() {
    // 清除定时器
    if(updateTimer) clearInterval(updateTimer);
    // 销毁地图实例
    if(mapInstance) mapInstance.remove();
    // 重置首次定位标记
    isFirstLocation = true;
}

// 通用渲染函数
async function renderISS(type) {
    // 先清理旧资源
    clearOldResource();
    // 获取当前场景配置
    const config = renderConfig[type];
    // 初始化地图
    mapInstance = L.map('issMap').setView([0, 0], 1);
    L.tileLayer(tileUrl, { attribution }).addTo(mapInstance);
    // 初始化标记
    const markerOption = config.icon ? {icon: config.icon} : {};
    markerInstance = L.marker([0, 0], markerOption).addTo(mapInstance);

    // 更新位置逻辑
    async function updatePosition() {
        const response = await fetch(apiUrl);
        const data = await response.json();
        const { latitude, longitude } = data;
        markerInstance.setLatLng([latitude, longitude]);
        if (isFirstLocation) {
            mapInstance.setView([latitude, longitude], 5);
            isFirstLocation = false;
        }
        document.getElementById('lat').textContent = latitude.toFixed(3);
        document.getElementById('lon').textContent = longitude.toFixed(3);
    }
    // 立即执行一次,之后每秒刷新
    updatePosition();
    updateTimer = setInterval(updatePosition, 1000);
}

// 页面加载默认执行带图标展示
window.onload = () => renderISS(1);

// 绑定所有链接的点击事件
document.querySelectorAll('.link').forEach(link => {
    link.addEventListener('click', () => {
        const type = link.getAttribute('data-type');
        renderISS(type);
    })
})

多场景需求通用实现方案

  • 优先使用配置表模式替代switch case,后续新增场景仅需新增配置项,无需修改核心渲染逻辑,符合开闭原则,维护成本更低
  • 如果场景存在逻辑差异而非仅参数差异,可在配置表中存储对应处理函数,直接调用即可,同样不需要修改核心逻辑
  • 所有状态、实例全局统一存储,切换前必须做资源清理,避免内存泄漏与性能问题
  • 公共逻辑统一封装,差异化内容从配置中读取,最大程度减少重复代码

如果确实需要用switch case实现,可把配置读取部分替换为如下逻辑:

function getConfigByType(type) {
    switch(type) {
        case '1':
            return {
                icon: L.icon({
                    iconUrl: "iss200.png",
                    iconSize: [75, 75],
                })
            }
        case '2':
            return { icon: null }
        case '3':
            return {
                icon: L.icon({
                    iconUrl: "other-satellite.png",
                    iconSize: [50, 50],
                })
            }
        default:
            return renderConfig['1']
    }
}

内容的提问来源于stack exchange,提问作者user14584183

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 08:48:00