RN Web + Firebase:快照侦听器取消订阅卸载与全局卸载(使用上下文)
RN Web + Firebase: snapshot listeners unsubscribe in unmount vs in global unmount (using context)
简而言之:使用 Firestore 快照侦听器、始终在屏幕卸载时卸载它们或在上下文中具有取消订阅功能并在整个站点“卸载”时卸载,这是最内存+成本效益的方式吗?
假设在主屏幕上我使用快照侦听器来收集“事件”,其中包含 100 个文档。现在,我在使用该网站期间浏览该网站并 return 到主屏幕 2 次以上。在这种情况下,哪个内存更好,成本效率更高(是否还有其他需要考虑的事情)并且有缺点吗?
- 在每次挂载和卸载主屏幕时挂载和卸载侦听器。
- 在主屏幕上挂载并在整个站点中卸载“卸载”(例如使用
window.addEventListener('beforeunload', handleSiteClose
)。
第一个的用法可能是大多数人所熟悉的,但是第二个的用法可以这样来完成:
-在以集合名称为键的上下文中保存监听器取消订阅函数:
const { listenerHolder, setListenerHolder } = DataContext();
useEffect(() => {
const newListeners = anyDeepCopyFunction(listenerHolder);
const collection = 'events';
if (listenerHolder[collection] === undefined) {
//listenerBaseComponent would be function to establish listener and return unsubscribe function
const unSub = listenerBaseComponent();
if (unSub)
newListeners[collection] = unSub;
}
if (Object.entries(newListeners).length !== Object.entries(listenerHolder).length) {
setListenerHolder(newListeners);
}
}, []);
-卸载所有监听器(在包含所有屏幕的组件中,并且仅在整个站点关闭时卸载):
const { listenerHolder, setListenerHolder } = DataContext();
const handleTabClosing = () => {
Object.entries(listenerHolder).forEach(item => {
const [key, value] = item;
if (typeof value === 'function')
value();
});
setListenerHolder({});
}
useEffect(() => {
window.addEventListener('beforeunload', handleTabClosing)
return () => {
window.removeEventListener('beforeunload', handleTabClosing)
}
})
在这两种情况下,主屏幕都显示“事件”集合中的最新信息,但据我所知...
-第一种方法创建监听器 3 次以收集“事件”,因此完成 3 x 100 次读取操作。
-第二种方法创建侦听器 1 次以收集“事件”,因此完成 1 x 100 次读取操作。
如果可以将取消订阅功能存储到上下文中,并且所有侦听器取消订阅都在站点卸载或注销时立即处理,这不是使以这种方式使用它变得超级容易、更易于维护且更具成本效益吗?如果我需要在任何其他屏幕上查看来自“事件”集合的数据,我就不必调用/创建一个新的监听器,因为在使用网站时我总是会从“事件”中获得最新数据。只需检查(在本例中)是否有集合名称作为全局状态“listenerHolder”中的键,如果有,则始终会有事件的最新数据。
由于没有其他人提供的关于这个用例的信息,我自己做了一些测试,多次从这个“主屏幕”跳到另一个屏幕。 “主屏幕”有大约 150 个项目,第二个屏幕有 65 个。
结果来自 Firebase,Cloud Firestore 使用选项卡:
这是该跳跃的读取结果:654(1.52pm-1.53pm) + 597(1.53pm-1.54pm) = 1251 读取
现在我测试了使用全局上下文侦听器时相同的来回跳跃:61(1.59pm-2.00pm) + 165(2.00pm-2.01pm) = 226 次读取
因此,在全局上下文中使用侦听器会导致读取次数显着减少。这取决于需要重新创建多少次新侦听器(在正常用例中)。
我还没有测试足够好的内存使用情况来比较这两种情况。但是如果我测试它,我会在这里添加结果以供其他人受益。
简而言之:使用 Firestore 快照侦听器、始终在屏幕卸载时卸载它们或在上下文中具有取消订阅功能并在整个站点“卸载”时卸载,这是最内存+成本效益的方式吗?
假设在主屏幕上我使用快照侦听器来收集“事件”,其中包含 100 个文档。现在,我在使用该网站期间浏览该网站并 return 到主屏幕 2 次以上。在这种情况下,哪个内存更好,成本效率更高(是否还有其他需要考虑的事情)并且有缺点吗?
- 在每次挂载和卸载主屏幕时挂载和卸载侦听器。
- 在主屏幕上挂载并在整个站点中卸载“卸载”(例如使用
window.addEventListener('beforeunload', handleSiteClose
)。
第一个的用法可能是大多数人所熟悉的,但是第二个的用法可以这样来完成:
-在以集合名称为键的上下文中保存监听器取消订阅函数:
const { listenerHolder, setListenerHolder } = DataContext();
useEffect(() => {
const newListeners = anyDeepCopyFunction(listenerHolder);
const collection = 'events';
if (listenerHolder[collection] === undefined) {
//listenerBaseComponent would be function to establish listener and return unsubscribe function
const unSub = listenerBaseComponent();
if (unSub)
newListeners[collection] = unSub;
}
if (Object.entries(newListeners).length !== Object.entries(listenerHolder).length) {
setListenerHolder(newListeners);
}
}, []);
-卸载所有监听器(在包含所有屏幕的组件中,并且仅在整个站点关闭时卸载):
const { listenerHolder, setListenerHolder } = DataContext();
const handleTabClosing = () => {
Object.entries(listenerHolder).forEach(item => {
const [key, value] = item;
if (typeof value === 'function')
value();
});
setListenerHolder({});
}
useEffect(() => {
window.addEventListener('beforeunload', handleTabClosing)
return () => {
window.removeEventListener('beforeunload', handleTabClosing)
}
})
在这两种情况下,主屏幕都显示“事件”集合中的最新信息,但据我所知...
-第一种方法创建监听器 3 次以收集“事件”,因此完成 3 x 100 次读取操作。
-第二种方法创建侦听器 1 次以收集“事件”,因此完成 1 x 100 次读取操作。
如果可以将取消订阅功能存储到上下文中,并且所有侦听器取消订阅都在站点卸载或注销时立即处理,这不是使以这种方式使用它变得超级容易、更易于维护且更具成本效益吗?如果我需要在任何其他屏幕上查看来自“事件”集合的数据,我就不必调用/创建一个新的监听器,因为在使用网站时我总是会从“事件”中获得最新数据。只需检查(在本例中)是否有集合名称作为全局状态“listenerHolder”中的键,如果有,则始终会有事件的最新数据。
由于没有其他人提供的关于这个用例的信息,我自己做了一些测试,多次从这个“主屏幕”跳到另一个屏幕。 “主屏幕”有大约 150 个项目,第二个屏幕有 65 个。
结果来自 Firebase,Cloud Firestore 使用选项卡:
这是该跳跃的读取结果:654(1.52pm-1.53pm) + 597(1.53pm-1.54pm) = 1251 读取
现在我测试了使用全局上下文侦听器时相同的来回跳跃:61(1.59pm-2.00pm) + 165(2.00pm-2.01pm) = 226 次读取
因此,在全局上下文中使用侦听器会导致读取次数显着减少。这取决于需要重新创建多少次新侦听器(在正常用例中)。
我还没有测试足够好的内存使用情况来比较这两种情况。但是如果我测试它,我会在这里添加结果以供其他人受益。