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

Svelte定时拉取数据库数据时如何避免已挂载组件弹窗意外关闭

问题根因

Svelte的{#await}块默认逻辑是:只要绑定的Promise引用发生变更,就会直接销毁块内所有已渲染的DOM和子组件实例,重新回到pending状态,等新Promise resolve后再从零创建子组件渲染。
你现在的定时任务每分钟都会给finishedPromise赋值一个全新的Promise对象,直接触发了顶层{#await}块的全量重渲染,嵌套的ManageDelivery组件被整个卸载后重新挂载,组件内部存的showModal本地状态会随着组件销毁被完全清空,弹窗自然就自动关闭了。


解决方案

方案1:响应式变量存异步结果(推荐,无副作用)

不要在模板层直接await会被替换引用的Promise,把异步拉取到的业务数据存在普通响应式变量里,用条件判断只处理首次加载状态,后续定时更新只修改变量值,全程不触发子组件销毁重建。
代码改法参考:

<script>
  import { onMount } from 'svelte';
  // 响应式变量存路由数据,初始为null代表首次加载中
  let routes = null;
  let selectedTab = 1;

  // 抽离数据拉取逻辑
  const loadData = async () => {
    const finisheds = await DataStorage.get('finished', true);
    // 这里补上你原来生成filteredRoutes的处理逻辑,最终赋值给routes
    routes = finisheds;
  };

  onMount(async () => {
    const depots = await depotsPromise;
    depots.forEach(depot => checkedDepots.add(depot._id));
    toRouteFilter = toRouteFilter;
    // 首次加载数据
    await loadData();
    // 启动定时更新
    const refreshTimer = setInterval(loadData, 60 * 1000);
    return () => clearInterval(refreshTimer);
  });
</script>

<div>
  {#if routes === null}
    Carregando...
  {:else}
    {#if selectedTab == 1}
      <ManageDelivery routes={routes} />
    {:else}
      <MapDelivery />
    {/if}
  {/if}
</div>

改完之后ManageDelivery组件在首次加载完成后只会挂载一次,后续每分钟的更新只会把最新的routes作为props传入组件,不会触发组件卸载,内部的弹窗状态、表单输入、焦点等所有本地状态都会完整保留,只需要在子组件里用响应式声明处理props变化后的派生数据更新即可。

方案2:状态上移(应急方案,不推荐)

如果暂时不想改动现有数据拉取逻辑,可以把ManageDelivery内部控制弹窗显隐的showModal状态提升到父组件维护,通过props传给子组件,弹窗开关事件通过父组件回调触发。
这种方案下就算子组件被定时任务触发重渲染,状态存在父组件不会丢失,子组件重新挂载时会根据传入的props值自动打开弹窗。但缺点很明显:每次更新子组件都会被重建,除了弹窗之外的其他本地状态(比如表单输入内容、列表滚动位置、焦点状态)都会被重置,体验很差,只适合临时救急用。

方案3:固定Promise引用

如果一定要保留Promise写法,不要每次更新都给finishedPromise赋值新的Promise实例,可以初始化一个带外部resolve方法的常驻Promise,后续更新只调用resolve传新值,保证模板绑定的Promise引用全程不变,也不会触发{#await}块重渲染。但这个写法绕弯,维护成本比方案1高,不优先选。


内容的提问来源于stack exchange,提问作者Vitor Bernstorff Clemes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:57:16