NodeJS 数组和 firebase 引用获取垃圾收集
NodeJS array and firebase reference getting garbage collected
我希望能够在第一个用户连接到 socket.io 房间时创建一些 firebase 引用,然后监听这些 firebase 引用的变化,并写入文件。
现在我的方法是拥有一个全局 Map 对象,然后将 firebase 引用和文件名作为对象的一部分分配给数组。然后存储对象,到全局地图。
不幸的是,一旦第一次连接的功能结束,引用就会丢失。我可以通过让另一个用户连接/刷新页面并记录全球地图来看到这一点。
这是我的代码的样子。
io.on('connect', (socket) => {
io.to(socket.id).emit('create-room');
socket.on('join-room', (roomId: string) => {
socket.join(roomId);
try {
console.log(activeWorkers)
if (!activeWorkers.get(roomId)) {
// if not in global map, tell user he is first in room so that we can get additional info
io.to(socket.id).emit('first-in-room');
} else {
console.log(activeWorkers.get(roomId));
}
} catch(err) {
console.log(err);
}
});
socket.on('create-worker', async (roomId: string, additionalInfo: string) => {
// first user sent back additional info;
let firebaseRefObj = new FirebaseRefObj(roomId, additionalInfo); // an object that stores the references and file paths
activeWorkers.set(roomId, {
id: roomId,
worker: firebaseRefObj
}); // store in global map
firebaseRefObj.createRefs(); // create references, the references add initial values to firebase, then watch for changes to update local files.
})
socket.on("disconnect", () => {
socket.removeAllListeners();
});
})
这是因为 socket.io 函数不会在 on
事件中保留它们的变量,如果您稍后尝试访问 firebaseRefObj
,则必须存储它放入数组或对象映射中,以便您可以将该用户与其重新关联。
您可以使用已有的房间 ID,并将其作为引用列表中值的名称传递 {[roomId]: firebaseRefObj}
就我个人而言,我强烈建议针对此用例使用 enmap
,enmap
就像 node.js 的 C# 字典。当您启动脚本并声明变量时,在顶部添加一个新的 enmap 来存储您的 ref 对象。
我相信以下方法会奏效:
const Enmap = require("enmap");
const FirebaseRefs = new Enmap();
// ...
FirebaseRefs.set(RoomId, FirebaseRefsObj);
您可以在这里阅读基础知识:https://enmap.evie.dev/usage/basic
Enmap 是一个非常好的解决方案,但我的问题在于我使用我的 firebase 引用的原因。我在内部使用 firepad,它本身与超出范围的 firebase 参考一起使用。
删除 firepad 解决了我的问题。
我希望能够在第一个用户连接到 socket.io 房间时创建一些 firebase 引用,然后监听这些 firebase 引用的变化,并写入文件。
现在我的方法是拥有一个全局 Map 对象,然后将 firebase 引用和文件名作为对象的一部分分配给数组。然后存储对象,到全局地图。 不幸的是,一旦第一次连接的功能结束,引用就会丢失。我可以通过让另一个用户连接/刷新页面并记录全球地图来看到这一点。
这是我的代码的样子。
io.on('connect', (socket) => {
io.to(socket.id).emit('create-room');
socket.on('join-room', (roomId: string) => {
socket.join(roomId);
try {
console.log(activeWorkers)
if (!activeWorkers.get(roomId)) {
// if not in global map, tell user he is first in room so that we can get additional info
io.to(socket.id).emit('first-in-room');
} else {
console.log(activeWorkers.get(roomId));
}
} catch(err) {
console.log(err);
}
});
socket.on('create-worker', async (roomId: string, additionalInfo: string) => {
// first user sent back additional info;
let firebaseRefObj = new FirebaseRefObj(roomId, additionalInfo); // an object that stores the references and file paths
activeWorkers.set(roomId, {
id: roomId,
worker: firebaseRefObj
}); // store in global map
firebaseRefObj.createRefs(); // create references, the references add initial values to firebase, then watch for changes to update local files.
})
socket.on("disconnect", () => {
socket.removeAllListeners();
});
})
这是因为 socket.io 函数不会在 on
事件中保留它们的变量,如果您稍后尝试访问 firebaseRefObj
,则必须存储它放入数组或对象映射中,以便您可以将该用户与其重新关联。
您可以使用已有的房间 ID,并将其作为引用列表中值的名称传递 {[roomId]: firebaseRefObj}
就我个人而言,我强烈建议针对此用例使用 enmap
,enmap
就像 node.js 的 C# 字典。当您启动脚本并声明变量时,在顶部添加一个新的 enmap 来存储您的 ref 对象。
我相信以下方法会奏效:
const Enmap = require("enmap");
const FirebaseRefs = new Enmap();
// ...
FirebaseRefs.set(RoomId, FirebaseRefsObj);
您可以在这里阅读基础知识:https://enmap.evie.dev/usage/basic
Enmap 是一个非常好的解决方案,但我的问题在于我使用我的 firebase 引用的原因。我在内部使用 firepad,它本身与超出范围的 firebase 参考一起使用。
删除 firepad 解决了我的问题。