auto-novel icon indicating copy to clipboard operation
auto-novel copied to clipboard

Sakura工作区任务列表有时无法在点击「排队Sakura」后更新,以及稳定复现此bug的方法

Open Volta-XTY opened this issue 1 year ago • 8 comments

一般来说,在任何一个tab点击「排队Sakura」时,如果此时有tab处在「Sakura工作区」页面,那么应该会自动将这个任务添加进来,然而实际有时并不能保持同步。

复现方法:

  1. 我自己是新开了一个 Firefox 隐私浏览窗口。
  2. 打开小说站,切换到 Sakura 页面,不过在此之前先要登录。这一步打开的 tab 记作 Tab0。
  3. 新开一个 tab,随便切到某个小说页面点击「排队Sakura」,新打开的 tab 记作 Tab1。
  4. Tab0 的任务队列正确地新增了 Tab1 排队的任务。
  5. 将 Tab1 切换到「Sakura工作区」页面,这个时候两个tab都是「Sakura工作区」。
  6. Tab0 随便切换到某个小说页面点击「排队Sakura」。
  7. 发现 Tab1 的任务队列没有新增排队任务。这个 bug 就复现完成了。

复现以后,查看 localStorage 可以发现,在 Tab0 点击「排队 Sakura」时,实际上 localStorage 完全没有更新,因此 Tab1 自然无法新增排队任务了。

实际上并不是 localStorage 的 hook 出了问题,而是某些情况下无法正确监测并更新 localStorage,所以大概这个问题还是比较好定位和修复的吧,所以先只是描述了具体问题,假若能简单修复就再好不过了。

Volta-XTY avatar Oct 15 '24 11:10 Volta-XTY

这个问题我觉得大概是来自vueuse本身的实现,可能不好搞。

FishHawk avatar Oct 16 '24 13:10 FishHawk

这个问题我觉得大概是来自vueuse本身的实现,可能不好搞。

我看了一下,大概是useLocalStorage()返回的ref在切换一次页面以后就不再和 localStorage 同步了,确实大概不好搞,尝试更新了vueuse/core也无法解决。姑且想到几个解决办法:

  1. 在每次调用addJob()等方法时,多写一行const ref = useLocalStorage(...)。这样可以保证写时与 localStorage 同步,但是无法保证读时与 localStorage 同步。

  2. 直接把Locator.sakuraWorkspaceRepository: lazy(...)套的lazy()直接去掉,每次获取workspace时,都是一个新的 Ref。这样就可以保证读写时均与 localStorage 同步,如果可以保证,切换页面时,必定调用Locator.sakura...()方法,那么所有的 Ref 就都是有效的。然而既然套了一层lazy,大概是有其他作用,所以不是很想用这种方法,感觉以后会出问题。

  3. 提前Locator.sakuraWorkspaceRepository()第一次调用的时机。在App.vue里面额外加入一行const _ = Locator.sakuraWorkspaceRepository()(空读一次),似乎确实可以解决问题。但是这样说实话还是不太优雅,而且我不太清楚为什么这样可以 work,是凭借直觉猜出来的。不过确实仅这一行代码就可以解决问题(不过我还把vueuse升级到11.0.1了),当然或许也要对 GPT Workspace 如法炮制。

  4. 当然了,还有一个方法就是把useLocalStorage()整个丢掉,如果觉得前面的解决方案都不行的话,整个丢掉也不是不行。问题在于动刀有点狠,不好说有没有新bug。不过优点是看不见的地方变少了,就算出bug也好调试。

上面的大概就是我自己搞了搞之后的报告。我自己是想用方法3啦。

无关:我自己调试前端的时候,会爆大量的500错误,此时命令行显示: ERROR 00:44:59 [vite] http proxy error: /api/wenku/6707c74ff223ee75285fc643 Error: read ECONNRESET at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) 这个是正常的吗?

Volta-XTY avatar Oct 16 '24 16:10 Volta-XTY

500错误我这边没见到,wenku元数据没理由出错才对,搞不懂。

解决方案我明天看下。

FishHawk avatar Oct 16 '24 17:10 FishHawk

const lazy = <T>(factory: () => T) => {
  let value: T | undefined;
  const get = () => {
    if (value === undefined) {
      value = factory();
    }
    return value;
  };
  return get;
};

这个bug的是因 lazy 函数造成的

useLocalstorage 内部使用了 watch 去检测 data 变化更新 localstorage

然而 watch 是 Vue 的响应式系统挂载在当前组件,组件卸载后会被清理,lazy 函数只会初始化执行一次,相当于 watch 在新的页面里没有重新执行导致整体功能失效了

有两种修复方式

  • 删除 lazy
  • 使用 onUnmounted 在卸载时清除缓存
const lazy = <T>(factory: () => T) => {
  let value: T | undefined;
  const get = () => {
    if (value === undefined) {
      value = factory();
+      onUnmounted(()=>{
+        value = undefined;
+      })
    }
    return value;
  };
  return get;
};

IronKinoko avatar Apr 03 '25 13:04 IronKinoko

进一步分析后,发现是node_modules/@vueuse/core/index.mjsuseStorage的这一段用了tryOnMounted来添加listener。当组件卸载时,listener就会被移除,并且无视外面的effectScope或是createGlobalState。删掉tryOnMounted直接加listener就正常了。

  if (window && listenToStorageChanges) {
    tryOnMounted(() => {
      useEventListener(window, "storage", update);
      useEventListener(window, customStorageEventName, updateFromCustomEvent);
      if (initOnMounted)
        update();
    });
  }

但是诡异的是在复现这个bug的时候,用createGlobalState包装了下就好了,还要再看看为什么。

复现代码:https://stackblitz.com/edit/vitejs-vite-47i1zttd?file=src%2Fstorage.ts

FishHawk avatar Apr 05 '25 06:04 FishHawk

我看了下 createGlobalState 的源码

function effectScope(detached?: boolean): EffectScope

内部使用了 effectScope(true),应该是 detached 参数把 watch 之类的与组件分离了吧

这里刚好有 lazy 情况的描述 https://github.com/vuejs/rfcs/blob/master/active-rfcs/0041-reactivity-effect-scope.md#detached-nested-scopes

IronKinoko avatar Apr 05 '25 07:04 IronKinoko

我看了下 createGlobalState 的源码

function effectScope(detached?: boolean): EffectScope

内部使用了 effectScope(true),应该是 detached 参数把 watch 之类的与组件分离了吧

这里刚好有 lazy 情况的描述 https://github.com/vuejs/rfcs/blob/master/active-rfcs/0041-reactivity-effect-scope.md#detached-nested-scopes

我这边测试,在机翻站代码里没用,在复现的用例里面有用,非常神秘

FishHawk avatar Apr 05 '25 07:04 FishHawk

已反馈给VueUse

https://github.com/vueuse/vueuse/issues/4695

FishHawk avatar Apr 05 '25 16:04 FishHawk

修复后会引入新问题,ls无法写入,刷新后数据失效

FishHawk avatar Jun 16 '25 17:06 FishHawk

这次应该修好了

FishHawk avatar Jul 04 '25 12:07 FishHawk