内存泄漏,如何在 React App 中避免它们。
什么是内存泄漏?
根据维基百科,内存泄漏是一种资源泄漏,当计算机程序错误地管理内存分配,导致不再需要的内存未被释放时,就会发生内存泄漏。当对象存储在内存中,但无法被正在运行的代码访问时,也可能会发生内存泄漏。
简而言之,只要内存中存在无法访问或未被引用的数据,就会发生内存泄漏。如今,许多现代编程语言都提供了清除不再需要的数据的技术,即垃圾回收。但事实证明,还有其他一些不太常见的错误可能会导致您的 React 应用面临内存泄漏的风险,并在很大程度上降低应用的性能。
让我们看看内存泄漏的一些原因。
React 应用程序中内存泄漏的原因
React 应用程序中的内存泄漏主要是由于在组件卸载之前未取消组件挂载时所做的订阅。这些订阅可能是 DOM 事件监听器、WebSocket 订阅,甚至是 API 请求。
前两个不太难,因为我们可以在组件卸载之前轻松地移除事件监听器或取消 WebSocket 订阅。但最后一个可能需要一些额外的工作。
典型的 React 工作流程
import { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
const MyCompany = function() {
const [ company, setCompany ] = useState(null);
useEffect(() => {
(async () {
const { data } = await axios.get(
'https://random-data-api.com/api/company/random_company'
);
setCompany(data);
})();
}, []);
return (
<>
<pre>{JSON.stringify(company, null, 3)}</pre>
<Link to = '/anotherpage'>Another Interesting Page</Link>
</>
)
}
在上面的代码片段中,我们有一个简单的组件MyCompany
,当安装时,它会发出获取随机公司的请求,并将company
状态值设置为从 API 获取的值。
问题
假设我们的用户的互联网连接速度非常慢,然后决定离开当前页面转到另一个有趣的页面,则请求已经发出,我们的浏览器会期待响应,当收到响应时,将导致我们调用setState
不再安装的组件。
除了设置状态之外,我们的应用中还会有一些不重要的数据,而且我们无法访问它们。在用户使用应用时,这个过程会重复多次,导致无用且无法访问的数据填满有用的内存,并导致严重的性能问题。
我们已经看到了问题,我相信你明白了,现在让我们看看如何解决这个问题。
前进之路:AbortControllers
了解了问题之后,我们要做的就是在组件卸载时取消请求,确保我们不会从 API 获取任何数据。
那么,我们如何取消请求?AbortControllers
根据MDN的说明,AbortController 代表一个控制器对象,它允许你根据需要中止一个或多个 Web 请求。这解释得很清楚!
AbortController 的创建new AbortController()
语法如下:初始化 AbortController 类的一个实例。每个 AbortController 对象都有一个只读signal
属性,该属性会传入请求,以及一个abort()
方法,用于在需要取消请求时使用。
现在使用 AbortControllers,我们的代码应该如下所示:
import { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
const MyCompany = function() {
const [ company, setCompany ] = useState(null);
useEffect(() => {
let abortController;
(async () {
abortController = new AbortController();
let signal = abortController.signal;
// the signal is passed into the request(s) we want to abort using this controller
const { data } = await axios.get(
'https://random-data-api.com/api/company/random_company',
{ signal: signal }
);
setCompany(data);
})();
return () => abortController.abort();
}, []);
return (
<>
<pre>{JSON.stringify(company, null, 3)}</pre>
<Link to = '/anotherpage'>Another Interesting Page</Link>
</>
)
}
现在,当我们的用户导航到新页面时,我们的 AbortController 会取消请求,我们不必担心数据泄漏。
注意:在请求完成后调用 abortController.abort() 不会抛出任何错误。abortController 只是不会对已完成的请求采取任何操作。
在您的 Web 应用程序中使用 AbortControllers 可以帮助提高性能并防止内存泄漏,因此您应该实际使用它。
谢谢阅读❤❤
文章来源:https://dev.to/jeremiahjacinth13/memory-leaks-how-to-avoid-them-in-a-react-app-1g5e