v 友们帮忙看看这段我几年前写的 定时刷新 token 的 js 代码,为什么会内存泄露?

254 天前
 rookie2luochao

背景是这样,这段代码就是 token 过期前 2 分钟刷新下 token ,但是它会在我切换到其他网页之后(这个刷新 token 的网页不关闭,后台运行),过很长一段时间在切回来就可能爆内存(可能 12 小时,可能 24 小时?),但是时间太短不会爆内存,所以我一直没找到很好的办法去测试定位

timer 是 rxjs 的定时器操作符

export function RefreshTokenComp({
  refreshTokenActor,
}: {
  refreshTokenActor: RequestActor<{
    refreshToken: string;
  }>;
}) {
  const [access$, updateAccess] = useAccessMgr();
  const access = useObservable(access$) || {};
  const { refresh_token, expireAt } = access;

  const [refreshTokenRequest] = useRequest(refreshTokenActor, {
    onSuccess({ arg }) {
      updateAccess(fromOAuthToken(arg.data));
    },
  });

  useEffect(() => {
    if (!refresh_token) return;
    const expiresIn = moment(expireAt).diff(moment(), "s") - 120; // token 过期前二分钟左右刷新
    const sub = timer(expiresIn * 1000).subscribe(() => {
      refreshTokenRequest({ refreshToken: refresh_token });
    });
    return () => {
      sub.unsubscribe();
    };
  }, [refresh_token]);

  return null;
}
3333 次点击
所在节点    程序员
34 条回复
googleaccount
254 天前
@googleaccount 咋格式呢
```javascript
const subscriptionRef = useRef(null);

useEffeect(() => {
...
if (subscriptionRef.current) {
subscriptionRef.current.unsubscribe();
}
...
subscriptionRef.current = timer()
...
return () => {
subscriptionRef.current.unsubscribe();
};
}, [refresh_token]);
```
leokun
253 天前
这段代码不会出现内存泄漏
大家不妨设想一下 refresh_token, expireAt 每秒都在改变,这里也不会内存泄漏,内存泄漏应该在别处
IvanLi127
253 天前
改成每秒刷一次看看内存会不会快速上涨吧,单看这代码没看出太大问题
rookie2luochao
253 天前
@yuuko 待我好好定位一下,搞清楚了踢你
rookie2luochao
253 天前
@vanchKong 我们两这写法思路一样,就是我比你多了 deps 依赖
rookie2luochao
253 天前
@rabbbit 问题应该不在 timer 上,应该是 v 友说的还是在 timer 没清除上面找原因
rookie2luochao
253 天前
@lisxour 好的,你的截图看不到,我觉得也是需要学习一下分析工具了
rookie2luochao
253 天前
@renmu 你说的这个原理我也想过,这算正常机制呢,还是说需要怎么去避免
rookie2luochao
253 天前
@ZENGQH 所以我需要通过是否离开标签页做清除吗?会不会麻烦了
rookie2luochao
253 天前
@googleaccount 换到 ref 上面,确实可能更靠谱
rookie2luochao
253 天前
@leokun 内存泄漏大概率就是这里,我也是直观上看不出来代码有问题,主要还是应该对 react effect 的执行机制没有理解透彻,同事也没看出来,只能说把 deps 写全,我只写一个 token 依赖是因为 token 和 expireAt 是同步变的,所以我就只写了 token 这个依赖,然后用 ref 引用,然后多清除几次 unsubscribe ,但是这只是尝试的解决办法
vanchKong
253 天前
@rookie2luochao 另外,我想说,可以试一下将 timer 用 useState 去定义,我开发 rn 的时候,碰到一种情况,就是 timer 不是用 useState 定义的,然后直接 clearInterval ,但是 timer 依然在执行的情况。
rookie2luochao
253 天前
@vanchKong 嗯嗯,谢谢哈,像 V 友说的用 useRef 更靠谱一点,自己还是需要找到能定位这种内存泄漏的方法,虽然目前我的产品定位内存泄漏时间线,现在有解决办法了,我看不能找到一个简单方法去定位
realJamespond
253 天前
rxjs 初始化在 effect 中不应该加依赖项,依赖项应该用 ref 保存在 rxjs 中引用

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/1040538

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX