首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >未兑现的承诺是否会导致记忆泄漏?

未兑现的承诺是否会导致记忆泄漏?
EN

Stack Overflow用户
提问于 2022-01-31 08:13:53
回答 2查看 165关注 0票数 1

在一个React应用程序中,在执行类似于以下简化示例的搜索之前,我们将删除键盘输入:

代码语言:javascript
运行
复制
function App() {
  const inputRef = useRef();
  const [result, setResult] = useState();

  const timeout = useRef();

  useEffect(() => () => clearTimeout(timeout.current));

  const debouncedSearch = useCallback((text) => {
    clearTimeout(timeout.current);
    const p = new Promise((resolve, reject) => {
      timeout.current = setTimeout(async () => {
        const result = await axios.get("/search?q=" + text);
        resolve(result);
      }, 1500);
    });
    return p;
  }, []);

  const onChange = useCallback(() => {
    const fn = async () => {
      const result = await debouncedSearch(inputRef.current.value);
      //if the promise isn't fulfilled will this hold onto setResult?
      setResult(result);
    };
    fn();
  }, []);

  return (
    <div>
      <input ref={inputRef} onChange={onChange} />
      <div>{result}</div>
    </div>
  );
}

正如您所看到的,在onChange中,我们正在创建一个新的承诺,如果在1.5秒内调用之前的处理程序,那么您可以看到。

既然前面的承诺是创建的,但它们的状态仍然没有实现,那么它们是否会对setResult进行硬引用,后者也比以前的呈现状态更倾向于泄漏内存?

EN

Stack Overflow用户

发布于 2022-02-01 03:51:35

您可以使用AbortControllerthrow语句以及async functions来减少程序执行上下文的数量。throw语句将导致对异步函数的返回承诺的拒绝,在另一个异步函数中等待该承诺将将允诺拒绝转换为异常,您可以使用try...catch来防止异常出现。这将使所有承诺得以兑现,防止潜在的相关内存泄漏。

在本例中,我还为您的axios调用使用了一个模拟函数,调整了示例的返回值,并减少了debouce延迟(因为1500是一个很长时间的)。

TS游乐场

代码语言:javascript
运行
复制
<div id="root"></div><script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script><script src="https://unpkg.com/@babel/standalone@7.16.12/babel.min.js"></script><script>Babel.registerPreset('tsx', {presets: [[Babel.availablePresets['typescript'], {allExtensions: true, isTSX: true}]]});</script>
<script type="text/babel" data-type="module" data-presets="tsx,react">

const {useCallback, useEffect, useRef, useState} = React;

function wait (delayMs: number) {
  return new Promise(res => setTimeout(res, delayMs));
}

async function mockAxios (...params: Parameters<(typeof axios)['get']>) {
  await wait(30);
  return {data: params[0]};
}

function Example () {
  const acRef = useRef(new AbortController());
  const [result, setResult] = useState<string>();
  useEffect(() => () => acRef.current.abort(), []);

  const debouncedSearch = useCallback(async (text: string, delayMs: number) => {
    acRef.current.abort();
    const ac = new AbortController();
    acRef.current = ac;

    await wait(delayMs);
    if (ac.signal.aborted) throw new Error('Aborted');
    const url = `/search?q=${text}`;
    const {signal} = ac;

    const result = await mockAxios(url, {signal});
    // const result = await axios.get(url, {signal});

    return result.data;
  }, []);

  const onChange = useCallback(async (ev: React.ChangeEvent<HTMLInputElement>) => {
    try {
      const result = await debouncedSearch(ev.target.value, 1000);
      setResult(result);
    }
    catch {/* Intentionally empty */}
  }, [debouncedSearch]);

  return (
    <div>
      <input {...{onChange}} placeholder="test by typing here" />
      <div>{result}</div>
    </div>
  );
}

ReactDOM.render(<Example />, document.getElementById('root'));

</script>

票数 0
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70922887

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档